Stop the boot from waiting on a black screen for the console to answer

About 1 boot in 10 of an installed system stops on a black screen at
"Starting Switch Root" until a key is pressed. systemd 257 and later
asks the console for its size with ANSI escape sequences when PID 1
starts and waits for the reply; with Plymouth holding the VT the reply
sometimes never comes.

Measured in QEMU on repeated boots of one install: 3 hangs in 30 and 1
in 40 on the prebuilt UKI, 7 in 40 on the stock initramfs, every one of
them ended by pressing Enter; none in 40 with a serial console, none in
40 with plymouth.enable=0, and none in 80 with
systemd.tty.term.console=dumb, which makes systemd skip the query.
systemd fixed two variants of this in v261; Arch's 261.2 still shows it.

The parameter goes where the last Plymouth boot fix went (3f725531,
initramfs_async=0): into the packaged omarchy-defaults.conf for fresh
installs, and a migration rebuilds the boot image on existing systems,
once per machine, only where the booted command line lacks it. Nothing
visible changes under "quiet splash".

Refs #2931
This commit is contained in:
Emir Beganovic committed 2026-10-09 23:26:20 +02:00
1 parent 2519fd9a97
commit f03bf06742
4 files changed
+110

No files matched your search

@@ -0,0 +1,66 @@
#!/bin/bash
#
# The migration that puts systemd.tty.term.console=dumb into effect on an
# existing install: the package has already written the parameter into
# omarchy-defaults.conf, so what is left is rebuilding the boot image, once per
# machine, and only where it is needed.
set -euo pipefail
source "$(dirname "${BASH_SOURCE[0]}")/base-test.sh"
migration="$ROOT/migrations/1791581004.sh"
test_dir=$(mktemp -d)
trap 'rm -rf "$test_dir"' EXIT
stub_bin="$test_dir/bin"
mkdir -p "$stub_bin"
# sudo just drops the prefix; limine-mkinitcpio records that it ran.
printf '#!/bin/bash\nexec "$@"\n' >"$stub_bin/sudo"
printf '#!/bin/bash\necho rebuilt >>"${REBUILDS:?}"\n' >"$stub_bin/limine-mkinitcpio"
chmod +x "$stub_bin"/*
old_cmdline="root=PARTUUID=1 rw quiet splash initramfs_async=0"
new_cmdline="$old_cmdline systemd.tty.term.console=dumb"
run() { # booted cmdline, defaults conf
: >"$test_dir/rebuilds"
printf '%s\n' "$1" >"$test_dir/cmdline"
PATH="$stub_bin:$ROOT/bin:$PATH" REBUILDS="$test_dir/rebuilds" \
OMARCHY_RUNNING_CMDLINE="$test_dir/cmdline" OMARCHY_LIMINE_DEFAULTS_CONF="$2" \
OMARCHY_LIMINE_REBUILD_MARKER="$test_dir/marker" bash "$migration" >/dev/null
}
rebuilds() { wc -l <"$test_dir/rebuilds"; }
run "$old_cmdline" "$ROOT/etc/limine-entry-tool.d/omarchy-defaults.conf"
[[ $(rebuilds) == 1 && -e $test_dir/marker ]] ||
fail "a machine booted without the parameter did not get its boot image rebuilt"
pass "a machine booted without the parameter gets its boot image rebuilt, with the packaged defaults"
run "$old_cmdline" "$ROOT/etc/limine-entry-tool.d/omarchy-defaults.conf"
[[ $(rebuilds) == 0 ]] || fail "the rebuild ran a second time before a reboot"
pass "the rebuild runs once per machine, not once per user"
rm -f "$test_dir/marker"
run "$new_cmdline" "$ROOT/etc/limine-entry-tool.d/omarchy-defaults.conf"
[[ $(rebuilds) == 0 && ! -e $test_dir/marker ]] || fail "a machine that already boots with the parameter was rebuilt"
pass "a machine that already boots with the parameter is left alone"
grep -v "tty.term.console" "$ROOT/etc/limine-entry-tool.d/omarchy-defaults.conf" >"$test_dir/edited.conf"
run "$old_cmdline" "$test_dir/edited.conf"
[[ $(rebuilds) == 0 ]] || fail "a machine whose defaults leave the parameter out was rebuilt anyway"
pass "a machine whose defaults were edited to leave the parameter out is left alone"
# No Limine: the stand-in goes, and the PATH holds only what the migration
# needs, so a limine-mkinitcpio installed on the machine running this test is
# not found either.
rm "$stub_bin/limine-mkinitcpio"
mkdir -p "$test_dir/tools"
for tool in bash grep install cat; do ln -s "$(command -v "$tool")" "$test_dir/tools/$tool"; done
: >"$test_dir/rebuilds"
printf '%s\n' "$old_cmdline" >"$test_dir/cmdline"
PATH="$stub_bin:$ROOT/bin:$test_dir/tools" REBUILDS="$test_dir/rebuilds" \
OMARCHY_RUNNING_CMDLINE="$test_dir/cmdline" OMARCHY_LIMINE_DEFAULTS_CONF="$ROOT/etc/limine-entry-tool.d/omarchy-defaults.conf" \
OMARCHY_LIMINE_REBUILD_MARKER="$test_dir/marker" "$test_dir/tools/bash" "$migration" >/dev/null
[[ ! -e $test_dir/marker ]] || fail "a machine without Limine was marked as rebuilt"
pass "a machine without Limine is left alone"
+4
View File
@@ -10,6 +10,10 @@ grep -Fq 'KERNEL_CMDLINE[default]+=" initramfs_async=0"' "$packaged_defaults" ||
fail "the packaged Limine defaults still unpack the initramfs synchronously"
pass "packaged Limine defaults keep Plymouth alive at the LUKS prompt"
grep -Fxq 'KERNEL_CMDLINE[default]+=" systemd.tty.term.console=dumb"' "$packaged_defaults" ||
fail "the packaged Limine defaults let PID 1 wait for the console to answer a size query"
pass "packaged Limine defaults keep PID 1 from waiting on the console"
grep -Fxq 'BOOT_ORDER="linux-t2, linux-omarchy, linux-omarchy-*, *, *fallback, Snapshots"' "$packaged_defaults" ||
fail "packaged Limine defaults protect T2 Macs and prefer the exact Omarchy kernel elsewhere"
pass "packaged Limine defaults protect T2 Macs and prefer the exact Omarchy kernel elsewhere"