Skip to content
Merged
14 changes: 14 additions & 0 deletions migrations/1790327076.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
echo "Enable Wi-Fi resume recovery on Apple Silicon Macs with BCM4388"

# A failed detector or lspci keeps the migration pending instead of skipping it.
platform=$(omarchy-hw-platform)
[[ $platform == "apple-silicon" ]] || exit 0
devices=$(lspci -nn)
grep -E '14e4:4434' <<<"$devices" >/dev/null || exit 0

omarchy-setup-mac --system
# Setup skips the chip when the installed add-on predates it; stay pending until it doesn't.
if ! /usr/lib/omarchy-mac/wifi-supported; then
echo "Error: the installed omarchy-mac does not cover BCM4388 yet; update again to finish." >&2
exit 1
fi
6 changes: 3 additions & 3 deletions packages/omarchy-mac/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ Apple Silicon defaults and support services for Omarchy. Version: `0.1.0` (candi

This directory is self-contained. Copy it anywhere, run `./test/all`, then `./install /absolute/staging/root`. Staging requires Bash, coreutils and findutils; tests also use Python and systemd. Nothing is enabled or started by staging. The Arch recipe lives in `omarchy-mac/omarchy-pkgs-aarch64`, on `feature/omarchy-mac-package`, and pins a full collaboration-repository commit.

Runtime dependencies: `omarchy` (shared Apple hardware detector), Bash, coreutils, diffutils (cmp), grep, sed, gawk, systemd, pciutils, kmod, mkinitcpio, NetworkManager, iwd, Python, PipeWire, pipewire-pulse, libpulse (pactl), and WirePlumber. The existing desktop audio leaf still installs the protected Asahi speaker stack. See `ORIGINS.md` for extraction attribution.
Runtime dependencies: `omarchy` (the `omarchy-hw-platform` detector and its Apple predicate), Bash, coreutils, diffutils (cmp), grep, sed, gawk, systemd, pciutils, kmod, mkinitcpio, NetworkManager, iwd, Python, PipeWire, pipewire-pulse, libpulse (pactl), and WirePlumber. The existing desktop audio leaf still installs the protected Asahi speaker stack. See `ORIGINS.md` for extraction attribution.

## Setup contract

Install the matching runtime, settings and add-on candidates in one pacman transaction. Their transferred commands and user unit must have only one owner. On Apple Silicon, include `install/omarchy-apple.packages` alongside the desktop base package list before calling `omarchy-apply-system`. The desktop checks the package is already present before its network hardware setup; offline setup never downloads it.

Run `omarchy-mac-setup-system` as root on the target hardware (inside its target chroot for offline provisioning). An optional absolute root argument supports staging against the same target hardware without a bus. It retires only exact generated Wi-Fi, module and service files, retaining a `.omarchy-mac-retired` backup. It enables resume recovery only for BCM4378/BCM4387 on Apple Silicon; BCM4388 and Intel/T2 are excluded. No NetworkManager restart or driver reload occurs during setup. The backend applies when NetworkManager next starts; notch changes apply when appledrm next loads.
Run `omarchy-mac-setup-system` as root on the target hardware (inside its target chroot for offline provisioning). An optional absolute root argument supports staging against the same target hardware without a bus. It exits without changes unless `omarchy-hw-platform` reports `apple-silicon`, and fails if the detector does. It retires only exact generated Wi-Fi, module and service files, retaining a `.omarchy-mac-retired` backup; the `/etc/NetworkManager/conf.d/wifi_backend.conf` that earlier Apple installs wrote is one of them, and any edited copy stays in place and keeps precedence. It enables resume recovery only for BCM4378, BCM4387 and BCM4388 on Apple Silicon; Intel/T2 Macs are excluded. No NetworkManager restart or driver reload occurs during setup. The backend applies when NetworkManager next starts; notch changes apply when appledrm next loads.

Run `omarchy-mac-setup-user` as each target user with their HOME/XDG directories. It enables the vendor unit without a session bus. With a live bus it reloads the user manager, reports the effective unit and starts the mapper. Provisioning, first-run and the transition migration run setup; subsequent session starts only start the enabled unit, without reloading the user manager or repeating setup. The first desktop session does not depend on a bus existing during installation. Custom fragments, masks, activation links and headset policies are preserved; setup markers preserve explicit disables after initial setup. User gain state remains in `omarchy/asahi-mic-gain.json` under XDG_STATE_HOME. The desktop saves that state before restarting audio.

Expand All @@ -34,4 +34,4 @@ The desktop keyboard migration runs `omarchy-mac-setup-keyboard` on upgraded Mac

The mocked behavioral tests cover Wi-Fi health, disabled radio, journal cursor/backstop recovery, unload/load failures and chipset gates; microphone gain/mute, device choices, missing endpoints, rollback and daemon loss; setup covers fresh/upgrade/repeated/interrupted operations, two users, first-session activation, masks and overrides. Keyboard setup covers each fork's generated line, owner files and links, a single first decision across runs and users, one rebuild, rebuild retry, owed fork rebuilds, the Limine rebuild path and the live switch. The desktop retains migration and audio restart integration coverage.

Before release promotion, record physical M1/M2 suspend/resume and microphone tests, the top row after an upgrade (F10 mutes, Fn+F10 sends F10, before and after a reboot), effective configuration, package transaction, source/recipe revisions, and reboot evidence. Aurora needs separate evidence. A successful source test run or candidate build is not physical hardware qualification. Do not publish this candidate to the rolling feed automatically.
Before release promotion, record physical M1/M2 suspend/resume (including lid close on a BCM4388 Mac) and microphone tests, the top row after an upgrade (F10 mutes, Fn+F10 sends F10, before and after a reboot), effective configuration, package transaction, source/recipe revisions, and reboot evidence. Aurora needs separate evidence. A successful source test run or candidate build is not physical hardware qualification. Do not publish this candidate to the rolling feed automatically.
9 changes: 7 additions & 2 deletions packages/omarchy-mac/bin/omarchy-mac-setup-system
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,20 @@ set -euo pipefail
root=${1:-/}
root=${root%/}
[[ -z $root || $root == /* ]] || exit 2
omarchy-hw-apple-silicon || exit 0
# A detector failure stops setup rather than reading as another platform.
platform=$(omarchy-hw-platform)
[[ $platform == "apple-silicon" ]] || exit 0
share="$root/usr/share/omarchy-mac"

# Retire only byte-identical generated files, never links (including masks).
retire() {
local file=$1 original=$2
if [[ -f $file && ! -L $file ]] && cmp -s "$file" "$original"; then
if [[ -e $file.omarchy-mac-retired || -L $file.omarchy-mac-retired ]]; then
cmp -s "$file" "$file.omarchy-mac-retired" || return 1
if ! cmp -s "$file" "$file.omarchy-mac-retired"; then
echo "Error: $file.omarchy-mac-retired differs from $file; move it aside and rerun." >&2
return 1
fi
rm -- "$file"
else
mv -- "$file" "$file.omarchy-mac-retired"
Expand Down
2 changes: 1 addition & 1 deletion packages/omarchy-mac/bin/omarchy-wifi-resume-fix
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
# omarchy:hidden=true
# omarchy:requires-sudo=true

# The Broadcom firmware on Apple Silicon Macs (BCM4378/BCM4387) can wedge
# The Broadcom firmware on Apple Silicon Macs (BCM4378/BCM4387/BCM4388) can wedge
# across s2idle: scans fail with -52 and every association is rejected with
# status_code=16, which NetworkManager surfaces as a wrong password. Toggling
# the radio does not reset the chip firmware - only a driver reload does.
Expand Down
4 changes: 2 additions & 2 deletions packages/omarchy-mac/lib/wifi-supported
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/bin/bash
# BCM4388 (4434) is intentionally excluded; T2 Macs share the other PCI IDs.
# BCM4378, BCM4387 and BCM4388. T2 Macs share some of these IDs, so the platform decides first.
set -o pipefail
omarchy-hw-apple-silicon && lspci -nn | grep -E '14e4:(4425|4433)' >/dev/null
[[ $(omarchy-hw-platform) == "apple-silicon" ]] && lspci -nn | grep -E '14e4:(4425|4433|4434)' >/dev/null
72 changes: 68 additions & 4 deletions packages/omarchy-mac/test/setup-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,14 @@ source "$(dirname "$0")/base-test.sh"
work=$(mktemp -d)
trap 'rm -rf "$work"' EXIT
mkdir -p "$work/bin"
cat >"$work/bin/omarchy-hw-platform" <<'STUB'
#!/bin/bash
[[ -z ${PLATFORM_ERROR:-} ]] || { echo "Error: $PLATFORM_ERROR" >&2; exit 1; }
echo "${PLATFORM:-apple-silicon}"
STUB
cat >"$work/bin/omarchy-hw-apple-silicon" <<'STUB'
#!/bin/bash
[[ ${APPLE:-1} == 1 ]]
[[ $(omarchy-hw-platform) == "apple-silicon" ]]
STUB
cat >"$work/bin/lspci" <<'STUB'
#!/bin/bash
Expand Down Expand Up @@ -44,15 +49,42 @@ ln -s /dev/null "$unit"
"$setup" "$stage"
[[ $(readlink "$unit") == /dev/null && ! -s $CALLS ]] || fail 'mask survives setup'
rm "$unit"
for spec in '0 4433' '1 4434' '1 0000'; do
read -r apple wifi <<<"$spec"
APPLE=$apple WIFI_ID=$wifi "$setup" "$stage"
for spec in 'generic 4433' 'qualcomm 4434' 'apple-silicon 0000'; do
read -r platform wifi <<<"$spec"
PLATFORM=$platform WIFI_ID=$wifi "$setup" "$stage"
[[ ! -s $CALLS ]] || fail 'non-Apple and excluded hardware are untouched'
done
rm "$stage/var/lib/omarchy-mac/wifi-configured"
if SYSTEMCTL_STATUS=42 "$setup" "$stage"; then fail 'enable failure must be retryable'; fi
"$setup" "$stage"
pass 'fresh, upgrade, repeated, interrupted, overrides, masks and hardware gates'
# Each fresh root: recovery is enabled for BCM4378, BCM4387 and BCM4388 on Apple Silicon only.
for spec in 'apple-silicon 4425 1' 'apple-silicon 4433 1' 'apple-silicon 4434 1' 'apple-silicon 4488 0' \
'generic 4433 0' 'generic-aarch64 4434 0' 'qualcomm 4434 0'; do
read -r platform wifi enabled <<<"$spec"
fresh="$work/fresh-$platform-$wifi"
"$ROOT/install" "$fresh"
: >"$CALLS"
PLATFORM=$platform WIFI_ID=$wifi "$fresh/usr/bin/omarchy-mac-setup-system" "$fresh"
if (( enabled )); then
grep -q 'enable omarchy-wifi-resume-fix.service' "$CALLS" || fail "recovery enabled on $platform $wifi"
[[ -f $fresh/var/lib/omarchy-mac/wifi-configured ]] || fail "recovery setup recorded on $platform $wifi"
else
[[ ! -s $CALLS && ! -e $fresh/var/lib/omarchy-mac ]] || fail "recovery left off on $platform $wifi"
fi
done
# A detector that cannot decide stops setup before it changes anything.
fresh="$work/fresh-contradiction"
"$ROOT/install" "$fresh"
mkdir -p "$fresh/etc/NetworkManager/conf.d"
cp "$ROOT/legacy/wifi_backend.conf" "$fresh/etc/NetworkManager/conf.d/"
: >"$CALLS"
if PLATFORM_ERROR='contradictory platform identity' "$fresh/usr/bin/omarchy-mac-setup-system" "$fresh" 2>"$work/err"; then
fail 'a detector failure fails setup'
fi
grep -q 'contradictory platform identity' "$work/err" || fail 'setup reports the detector failure'
[[ -f $fresh/etc/NetworkManager/conf.d/wifi_backend.conf && ! -s $CALLS ]] || fail 'a detector failure changes nothing'
pass 'BCM4378, BCM4387 and BCM4388 on Apple Silicon only, and a detector failure stops setup'
for relative in etc/modprobe.d/asahi-notch.conf etc/NetworkManager/conf.d/wifi_backend.conf; do
file="$stage/$relative"
mkdir -p "${file%/*}"
Expand All @@ -63,6 +95,38 @@ for relative in etc/modprobe.d/asahi-notch.conf etc/NetworkManager/conf.d/wifi_b
"$setup" "$stage"
[[ $(cat "$file") == 'administrator override' ]] || fail 'modified config survives'
done
# Earlier Apple installs wrote the backend file with a heredoc or printf; both give these bytes.
backend="$stage/etc/NetworkManager/conf.d/wifi_backend.conf"
rm -f "$backend" "$backend.omarchy-mac-retired"
printf '%s\n' '[device]' 'wifi.backend=iwd' >"$backend"
"$setup" "$stage"
[[ ! -e $backend ]] && cmp -s "$backend.omarchy-mac-retired" "$ROOT/legacy/wifi_backend.conf" ||
fail 'the generated backend file retires with a backup'
cmp -s "$stage/usr/lib/NetworkManager/conf.d/20-omarchy-mac-wifi.conf" "$ROOT/legacy/wifi_backend.conf" ||
fail 'the vendor default keeps the retired setting'
# Any edit, even one that keeps iwd, is the administrator's file now.
for variant in '[device]\nwifi.backend=wpa_supplicant\n' '[device]\nwifi.backend=iwd\nwifi.scan-rand-mac-address=no\n' \
'# keep iwd\n[device]\nwifi.backend=iwd\n' '[device]\nwifi.backend=iwd'; do
rm -f "$backend"
printf '%b' "$variant" >"$backend"
cp "$backend" "$work/expected"
"$setup" "$stage"
cmp -s "$backend" "$work/expected" || fail 'an edited backend file survives setup' "$variant"
done
rm "$backend"
ln -s "$stage/usr/share/omarchy-mac/legacy/wifi_backend.conf" "$backend"
"$setup" "$stage"
[[ -L $backend ]] || fail 'a linked backend file survives setup'
rm "$backend"
# A backup the administrator changed is never overwritten; setup stops and says why.
printf 'administrator backup\n' >"$backend.omarchy-mac-retired"
cp "$ROOT/legacy/wifi_backend.conf" "$backend"
if "$setup" "$stage" 2>"$work/err"; then fail 'a changed backup blocks retirement'; fi
grep -q 'wifi_backend.conf.omarchy-mac-retired' "$work/err" || fail 'a blocked retirement names the backup'
[[ $(cat "$backend.omarchy-mac-retired") == 'administrator backup' ]] && cmp -s "$backend" "$ROOT/legacy/wifi_backend.conf" ||
fail 'a blocked retirement keeps both files'
rm "$backend" "$backend.omarchy-mac-retired"
pass 'the legacy backend file retires only unmodified and never loses an administrator edit'
user_setup="$stage/usr/bin/omarchy-mac-setup-user"
export XDG_RUNTIME_DIR="$work/no-session"
unset XDG_CONFIG_HOME XDG_STATE_HOME
Expand Down
14 changes: 12 additions & 2 deletions packages/omarchy-mac/test/systemd-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,22 @@ trap 'rm -rf "$work"' EXIT
mkdir -p "$work/root/etc/systemd/system" "$work/bin"
cp "$ROOT"/legacy/omarchy-wifi-resume-fix.service "$work/root/etc/systemd/system/"
systemctl --root="$work/root" enable omarchy-wifi-resume-fix.service
printf '#!/bin/bash\nexit 0\n' >"$work/bin/omarchy-hw-apple-silicon"
printf '#!/bin/bash\necho "14e4:4433"\n' >"$work/bin/lspci"
printf '#!/bin/bash\necho apple-silicon\n' >"$work/bin/omarchy-hw-platform"
printf '#!/bin/bash\necho "14e4:${WIFI_ID:-4433}"\n' >"$work/bin/lspci"
chmod +x "$work/bin/"*
PATH="$work/bin:$PATH" "$work/root/usr/bin/omarchy-mac-setup-system" "$work/root"
for target in suspend hibernate hybrid-sleep suspend-then-hibernate; do
link="$work/root/etc/systemd/system/$target.target.wants/omarchy-wifi-resume-fix.service"
[[ $(readlink "$link") == /usr/lib/systemd/system/omarchy-wifi-resume-fix.service ]] || fail 'legacy enablement points to vendor unit'
done
pass 'real systemctl upgrade repairs generated enablement links'

# A fresh BCM4388 Mac gets the vendor unit enabled for every sleep target.
"$ROOT"/install "$work/fresh"
WIFI_ID=4434 PATH="$work/bin:$PATH" "$work/fresh/usr/bin/omarchy-mac-setup-system" "$work/fresh"
for target in suspend hibernate hybrid-sleep suspend-then-hibernate; do
link="$work/fresh/etc/systemd/system/$target.target.wants/omarchy-wifi-resume-fix.service"
[[ $(readlink "$link") == "/usr/lib/systemd/system/omarchy-wifi-resume-fix.service" ]] || fail 'BCM4388 enables the vendor unit'
done
[[ ! -e $work/fresh/etc/systemd/system/omarchy-wifi-resume-fix.service ]] || fail 'fresh setup writes no /etc unit'
pass 'real systemctl enables recovery on a fresh BCM4388 Mac'
34 changes: 17 additions & 17 deletions packages/omarchy-mac/test/wifi-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -30,19 +30,11 @@ done
SH

# The recovery is for Apple Silicon, so every case has to say which
# architecture it runs on rather than inherit the machine running the suite.
cat >"$stub_bin/omarchy-hw-apple-silicon" <<'SH'
# platform it runs on rather than inherit the machine running the suite.
cat >"$stub_bin/omarchy-hw-platform" <<'SH'
#!/bin/bash
[[ ${ARCH:-x86_64} == aarch64 ]]
SH
cat >"$stub_bin/uname" <<'SH'
#!/bin/bash

if [[ ${1:-} == "-m" ]]; then
echo "${ARCH:-x86_64}"
else
exec /usr/bin/uname "$@"
fi
[[ ${PLATFORM:-generic} != "error" ]] || { echo "Error: contradictory platform identity" >&2; exit 1; }
echo "${PLATFORM:-generic}"
SH

cat >"$stub_bin/systemctl" <<'SH'
Expand Down Expand Up @@ -164,7 +156,7 @@ chmod +x "$stub_bin"/*
sed "s|/usr/lib/omarchy-mac/wifi-supported|$ROOT/lib/wifi-supported|" "$fix" >"$test_tmp/fix"
chmod +x "$test_tmp/fix"
fix="$test_tmp/fix"
export ARCH=aarch64 WIFI_ID=4433
export PLATFORM=apple-silicon WIFI_ID=4433

# The recovery command itself: wedge detection and the decision to reload.
run_fix() {
Expand Down Expand Up @@ -271,9 +263,17 @@ pass "a reload that never reconnects fails loudly"

out=$(LOAD_FAILS=1 run_fix) && fail "failed driver reload must fail" "$out"
grep -q 'failed to reload' <<<"$out" || fail "failed reload is diagnosed" "$out"
for spec in 'aarch64 4434' 'x86_64 4433' 'aarch64 0000'; do
read -r ARCH WIFI_ID <<<"$spec"
run_fix >/dev/null
[[ ! -s $calls ]] || fail "unsupported hardware must not reload"
for spec in 'generic 4433' 'generic-aarch64 4434' 'qualcomm 4425' 'error 4434' 'apple-silicon 4488' 'apple-silicon 0000'; do
read -r PLATFORM WIFI_ID <<<"$spec"
REJECT_LINES=2 run_fix >/dev/null 2>&1
[[ ! -s $calls ]] || fail "unsupported hardware must not reload" "$spec"
done
pass "failed reload and excluded chipsets are safe"

# BCM4378, BCM4387 and BCM4388 all wedge across s2idle, so each one recovers.
for WIFI_ID in 4425 4433 4434; do
PLATFORM=apple-silicon
out=$(REJECT_LINES=2 run_fix) || fail "a wedged $WIFI_ID recovers" "$out"
grep -Fxq $'modprobe\tbrcmfmac' "$calls" || fail "a wedged $WIFI_ID reloads the driver" "$(cat "$calls")"
done
pass "BCM4378, BCM4387 and BCM4388 recover on Apple Silicon"
Loading
Loading