Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions mac-manual/content/03-updates.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ When a kernel or boot package changes, `omarchy-mac-boot` rebuilds the initramfs

If that check fails, the update refuses to finish, says what failed and does not offer a reboot. Do not reboot. Keep the output and [report it]({{page:hardware}}#reporting-a-problem).

A Mac that boots a kernel or m1n1 its owner builds, rather than the packaged ones, can never pass that check. Its owner can say so by naming the chain on the first line of `/etc/omarchy-mac-boot/owner-boot-chain`. A failed check then still shows what it found, but the update finishes with a warning, and making sure the next boot works is up to the owner. While the file exists, every update says so, even when the check passes. To have updates verify the boot files again, for example after going back to the packaged kernel and m1n1, remove the file. Only `omarchy update` reads it: the check before a snapshot restore does not.

## What is signed, and by what

Nothing is trusted because of where it came from. Each artefact carries its own signature or digest, and each is checked on your Mac by something that was not downloaded alongside it.
Expand Down
25 changes: 23 additions & 2 deletions omarchy-mac-boot/entrypoints/update-verify
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,38 @@
# system ESP, and on a Limine Mac the loader, menu and UKI on that same ESP.
# The installed kernel may be newer than the running one until that reboot.
# Nothing here rebuilds a boot file.
#
# A Mac whose owner boots a chain this package does not build, such as a
# kernel or m1n1 built by hand, names it in /etc/omarchy-mac-boot/owner-boot-chain.
# There a failed check is reported as a warning and the update finishes. While
# the file exists, every update says so, even when the check passes, so that a
# declaration nobody needs any more is seen before it hides a real failure.

set -uo pipefail

owner_boot_chain=${OMARCHY_BOOT_CHECK_ROOT:-}/etc/omarchy-mac-boot/owner-boot-chain

echo -e "\e[32m\nVerify the Apple Silicon boot files\e[0m"
if ! OMARCHY_BOOT_CHECK_ALLOW_PENDING_REBOOT=1 omarchy-apple-silicon-boot-check --boot-chain; then
cat >&2 <<'MESSAGE'
if [[ -f $owner_boot_chain ]]; then
chain=$(grep -m 1 -v '^[[:space:]]*$' "$owner_boot_chain")
cat >&2 <<MESSAGE

The boot files were not verified: /etc/omarchy-mac-boot/owner-boot-chain says this Mac's owner manages its boot chain:
${chain:-(the file names no chain)}
The update finishes anyway. Before you reboot, make sure that chain boots what the update installed.
To have updates verify the boot files again, remove /etc/omarchy-mac-boot/owner-boot-chain.
MESSAGE
else
cat >&2 <<'MESSAGE'

This Mac might not boot what the update installed, so do not reboot yet.
Fix what the boot check reported above. To rebuild the initramfs, m1n1 and the boot menu:
sudo mkinitcpio -P && sudo update-m1n1 && sudo omarchy-mac-boot-update
Then run omarchy update again: it checks the boot files before it offers the reboot.
MESSAGE
exit 1
exit 1
fi
elif [[ -f $owner_boot_chain ]]; then
echo "Boot files verified; /etc/omarchy-mac-boot/owner-boot-chain is present, so a failed check would only warn."
fi
43 changes: 43 additions & 0 deletions omarchy-mac-boot/test/update-verify-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ limine_mac
verify
expect_verified "a Limine Mac running the installed kernel"
grep -Fq "running linux-aurora $mac_kver; installed boot files match" "$tmp/out" || fail "update-verify reports what it verified" "$(cat "$tmp/out")"
! grep -Fq "owner-boot-chain" "$tmp/out" "$tmp/err" || fail "a Mac without /etc/omarchy-mac-boot/owner-boot-chain is not told about it" "$(cat "$tmp/out" "$tmp/err")"
verify 6.16.0-aurora9-ARCH
expect_verified "a Limine Mac whose update installed a new kernel"
grep -Fq "running 6.16.0-aurora9-ARCH, reboot pending" "$tmp/out" || fail "update-verify says the reboot is still to come" "$(cat "$tmp/out")"
Expand Down Expand Up @@ -102,6 +103,48 @@ verify 6.16.0-aurora9-ARCH
expect_refused "an initramfs built for the previous kernel" "does not hold the $mac_kver modules"
pass "update-verify refuses a wrong device tree, a stale m1n1, a missing or stale UKI, another Limine or a stale initramfs, and says not to reboot"

# An owner who boots a chain this package does not build names it in
# /etc/omarchy-mac-boot/owner-boot-chain. A failed check then still shows
# what it found, but warns, says how to go back and lets the update finish.
# A passing check says the file is there, so it is not forgotten.
owner_boot_chain() {
mkdir -p "$mac_root/etc/omarchy-mac-boot"
printf '%s\n' "$@" >"$mac_root/etc/omarchy-mac-boot/owner-boot-chain"
}

expect_warned() {
local description=$1 reason=$2 chain=$3
(( status == 0 )) || fail "$description passes update-verify with a warning" "status $status: $(cat "$tmp/out" "$tmp/err")"
grep -Fq "$reason" "$tmp/err" || fail "$description still shows what the boot check found" "$(cat "$tmp/err")"
grep -Fq "The boot files were not verified: /etc/omarchy-mac-boot/owner-boot-chain says this Mac's owner manages its boot chain:" "$tmp/err" &&
grep -Fxq " $chain" "$tmp/err" || fail "$description names the owner's chain" "$(cat "$tmp/err")"
grep -Fxq "To have updates verify the boot files again, remove /etc/omarchy-mac-boot/owner-boot-chain." "$tmp/err" ||
fail "$description says how to have updates verify the boot files again" "$(cat "$tmp/err")"
! grep -Fq "do not reboot yet" "$tmp/err" || fail "$description does not say the update is unfinished" "$(cat "$tmp/err")"
}

limine_mac
owner_boot_chain "" "m1n1 and linux built by hand, booted from the owner's stage 2"
verify
expect_verified "an owner-managed Mac whose boot chain passes the check"
[[ ! -s $tmp/err ]] || fail "an owner-managed Mac that passes the check gets no warning" "$(cat "$tmp/err")"
grep -Fxq "Boot files verified; /etc/omarchy-mac-boot/owner-boot-chain is present, so a failed check would only warn." "$tmp/out" ||
fail "an owner-managed Mac that passes the check is told the file is present" "$(cat "$tmp/out")"
rm "$mac_esp/EFI/Linux/omarchy_linux-aurora.efi"
verify
expect_warned "an owner-managed Mac without its UKI" "/boot/efi/EFI/Linux/omarchy_linux-aurora.efi (the Limine UKI) is missing" \
"m1n1 and linux built by hand, booted from the owner's stage 2"

limine_mac
sed -i '/^linux-aurora$/d' "$mac_state/installed"
verify
expect_refused "a Mac with no packaged kernel" "cannot tell which kernel boots: neither linux-aurora nor linux-asahi installed"
owner_boot_chain ""
verify
expect_warned "an owner-managed Mac with no packaged kernel" "cannot tell which kernel boots: neither linux-aurora nor linux-asahi installed" \
"(the file names no chain)"
pass "update-verify warns instead of refusing on a Mac whose owner names the boot chain they manage, and says the file is present when the check passes"

# update-verify checks only what the next boot reads. What the full boot check
# also holds against a Mac, the next boot does not read, so it never fails an
# update: the full check still refuses it.
Expand Down
26 changes: 26 additions & 0 deletions test/integration/mac-update-boot-verify-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -101,3 +101,29 @@ limine_mac
rm "$mac_esp/EFI/Linux/omarchy_linux-aurora.efi"
blocked "a missing UKI" "/boot/efi/EFI/Linux/omarchy_linux-aurora.efi (the Limine UKI) is missing"
pass "apple: a wrong device tree, a stale m1n1 or a missing UKI fails the update, explained, with no reboot offered"

# A boot chain its owner names in /etc/omarchy-mac-boot/owner-boot-chain is
# reported, not enforced: the update finishes and offers the reboot.
limine_mac
rm "$mac_esp/EFI/Linux/omarchy_linux-aurora.efi"
mkdir -p "$mac_root/etc/omarchy-mac-boot"
printf 'a kernel and m1n1 stage 2 built by hand\n' >"$mac_root/etc/omarchy-mac-boot/owner-boot-chain"
run_update aarch64-apple "$tmp/mac-boot"
(( status == 0 )) && reboot_offered ||
fail "apple: an update on an owner-managed boot chain finishes and offers the reboot" "status $status: $(cat "$tmp/out" "$tmp/err")"
grep -Fq "/boot/efi/EFI/Linux/omarchy_linux-aurora.efi (the Limine UKI) is missing" "$tmp/err" &&
grep -Fq "says this Mac's owner manages its boot chain:" "$tmp/err" && grep -Fq "a kernel and m1n1 stage 2 built by hand" "$tmp/err" &&
grep -Fq "To have updates verify the boot files again, remove /etc/omarchy-mac-boot/owner-boot-chain." "$tmp/err" ||
fail "apple: an owner-managed boot chain shows what the check found, that it was not verified and how to go back" "$(cat "$tmp/err")"
! grep -Fq "The update is not finished" "$tmp/err" || fail "apple: an owner-managed boot chain does not leave the update unfinished" "$(cat "$tmp/err")"
pass "apple: an owner-managed boot chain that fails the check warns, and the update finishes with its reboot"

limine_mac
mkdir -p "$mac_root/etc/omarchy-mac-boot"
printf 'a kernel and m1n1 stage 2 built by hand\n' >"$mac_root/etc/omarchy-mac-boot/owner-boot-chain"
run_update aarch64-apple "$tmp/mac-boot"
(( status == 0 )) && reboot_offered ||
fail "apple: an update on an owner-managed boot chain that passes the check succeeds" "status $status: $(cat "$tmp/out" "$tmp/err")"
grep -Fq "Boot files verified; /etc/omarchy-mac-boot/owner-boot-chain is present, so a failed check would only warn." "$tmp/out" ||
fail "apple: an update on an owner-managed boot chain that passes the check says the file is present" "$(cat "$tmp/out")"
pass "apple: an owner-managed boot chain that passes the check still says the file is present"
Loading