Skip to content

Commit 78e88b3

Browse files
docs(notes): AMD boot-hang + Flatpak-bake incident post-mortem
Documents both June 2026 incidents from forum #12247 (Beelink SER8 / Ryzen 8745 / Radeon 780M): affected hardware, symptoms, every solution tried, the hypotheses and their fate, the root cause + resolution, the shared CI/dev-host blind spots, the truncated-ISO red herring, and the regression guards added.
1 parent 632d0c9 commit 78e88b3

1 file changed

Lines changed: 184 additions & 0 deletions

File tree

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
# Incident notes: AMD mini-PC live-ISO boot hang + fresh-install Flatpak bake (June 2026)
2+
3+
Two distinct bugs surfaced from the same uBlue forum thread
4+
([#12247](https://universal-blue.discourse.group/t/introducing-margine-os/12247))
5+
by tester **CyberOto** on the same hardware class (AMD Ryzen 8000 / Radeon
6+
780M mini-PCs). They are unrelated in cause but share two themes worth
7+
recording: **the dev host masked both bugs**, and **CI never exercised the
8+
path that broke**.
9+
10+
- **Incident 1 — live ISO hard-hangs on boot.** RESOLVED, PR #221.
11+
- **Incident 2 — fresh install lands with a broken /var/lib/flatpak.** Fixed
12+
PR #222 (upstream-alignment); definitive confirmation pending the
13+
real-install CI gate.
14+
15+
---
16+
17+
## Incident 1 — AMD mini-PC live-ISO boot hang (baked `console=ttyS0`)
18+
19+
### Affected hardware
20+
| Machine | CPU | iGPU | RAM | Result |
21+
|---|---|---|---|---|
22+
| Beelink SER8 (mini-PC) | Ryzen 7 8745(H) | Radeon 780M | 32 GB | **HANG** |
23+
| Second AMD desktop | Ryzen 7 8745 | Radeon 780M || **HANG** |
24+
| Tuxedo Pulse Gen3 (laptop) | Ryzen 7 7840 | Radeon 780M || boots fine |
25+
26+
Discriminators: same 780M iGPU works on the laptop but not the desktops;
27+
**stock Bluefin DX live ISO booted fine on the same desktops.**
28+
29+
### Symptoms
30+
- Margine live ISO: black screen shortly after peripheral init.
31+
- With `quiet rhgb` removed (verbose): the boot **crawls ~30x too slow**
32+
every systemd step ~30 s apart, even trivial socket units — reaches the
33+
initramfs, and **hard-hangs at ~700 s** during `systemd-modules-load`
34+
(right after the SCSI device handlers emc/rdac/alua). Keyboard then dead,
35+
no VT switch, no Caps/Num-Lock LED, no SSH, no ping.
36+
- Early ACPI BIOS error: `\_SB.PCI0.GPP5.RTL8._S0W, AE_ALREADY_EXISTS`.
37+
- Rebase to the installed image reached GDM, then froze on login, then disk
38+
write errors, then unbootable.
39+
40+
### Solutions tried
41+
| Attempt | Result |
42+
|---|---|
43+
| `amd_iommu=off` | no change |
44+
| `nomodeset` / `amdgpu.dc=0` | no change |
45+
| remove `quiet rhgb` | no fix, but revealed the verbose log (the 30x slowdown) |
46+
| Ctrl+Alt+F3 / Caps-Lock LED / SSH / ping | confirmed a true hard hang |
47+
| BIOS UMA = Auto / 8 GB / UMA_AUTO | no change (ruled out RAM/UMA) |
48+
| `processor.max_cstate=1` + remove `console=ttyS0` | booted |
49+
| **remove only `console=ttyS0,115200n8`** | **booted fully, no slowness — THE FIX** |
50+
| stock-Fedora-kernel test ISO, `console=ttyS0` removed | also booted (exonerates the kernel) |
51+
52+
### Hypotheses (and their fate)
53+
1. **CachyOS kernel regression on Ryzen 8000** (amd_sfh GPF / amd_pstate /
54+
C-state). Investigated with two multi-agent research passes + a
55+
stock-kernel A/B test ISO. **REFUTED:** the stock-Fedora-kernel ISO hung
56+
identically and was fixed by the same param.
57+
2. **RAM / UMA-VRAM exhaustion on the 780M.** **REFUTED:** 32 GB RAM, and
58+
changing the BIOS UMA setting made no difference.
59+
3. **ACPI `_S0W` / Realtek.** Benign, common AM5 ACPI warning; red herring.
60+
4. **Baked `console=ttyS0` stalling on a phantom UART.** Raised early as the
61+
one karg our ISO bakes that Bluefin's does not. **CONFIRMED** by CyberOto.
62+
63+
### Root cause
64+
The live ISO baked `console=tty0 console=ttyS0,115200n8
65+
systemd.show_status=1` into the default GRUB entries.
66+
`console=ttyS0` was added only so the CI QEMU boot-test could watch the
67+
serial console. On a board that advertises a **phantom 8250 UART** (common
68+
on mini-PCs like the Beelink SER8) the device never drains its TX FIFO, so
69+
every kernel `printk` busy-waits in `serial8250` until a timeout; with
70+
`systemd.show_status` forcing per-unit output that drags the whole boot ~30x
71+
slower and eventually wedges. Bluefin's ISO does not bake `console=ttyS0`,
72+
which is why it booted. The CachyOS kernel was a coincidence, not a cause.
73+
74+
### Resolution
75+
- **PR #221:** removed `console=ttyS0` + `systemd.show_status=1` from the two
76+
default ISO entries (now `console=tty0` only). CI keeps serial
77+
observability **without** the harmful karg by extracting the ISO's
78+
kernel+initrd and direct-booting them (`-kernel/-initrd/-append`, console
79+
injected there) while `-cdrom` serves the squashfs.
80+
- **PR #220 (audit hardening, same week):** a "verbose, no splash, no serial"
81+
recovery GRUB entry; bounded the live overlay (`rd.live.overlay.size`);
82+
refreshed `linux-firmware`/microcode after the kernel swap; zstd-guards on
83+
the initramfs regen; a squashfs-is-zstd CI assertion; a warn-only 2 GiB
84+
constrained CI boot pass.
85+
- Follow-up: republish a clean public ISO (the previously published one
86+
still carries the karg).
87+
88+
---
89+
90+
## Incident 2 — fresh install lands with a broken /var/lib/flatpak
91+
92+
### Affected hardware / scope
93+
Reported on the Beelink SER8 (Ryzen 8745, 32 GB) after a fresh ISO install,
94+
but the analysis concluded it affects **every fresh ISO install** on the
95+
default partitioning (dedicated `/var` btrfs subvol) — not SER8-specific.
96+
97+
### Symptoms (installed system, post-boot)
98+
- `margine-validate-margine-system`: all ~42 BAKE/preinstall apps "NOT
99+
installed" — "kickstart %post bake silently failed AND preinstall fallback
100+
hasn't caught it yet".
101+
- `flatpak-preinstall.service`: failed (exit 1), "Start request repeated too
102+
quickly, restart counter at 3" → permanently failed.
103+
- `flatpak update`: `Warning/error: opendir(refs/remotes): No such file or
104+
directory`; apps won't start; `sudo flatpak update` hung.
105+
106+
### Investigation + hypotheses
107+
A 24-agent analysis (with adversarial verification) found Margine **diverged
108+
from BOTH Bluefin and Bazzite** on four points of the bake/install path. The
109+
exact on-disk corruption mechanism did **not** fully converge — and, crucially,
110+
**it cannot be settled from the dev host because the host never exercised the
111+
bake path** (its Flatpaks came from the first-boot download fallback, which
112+
masks the bug). The four verified divergences (the actionable truth):
113+
114+
1. **SELinux labels stripped, never restored.** `install-flatpaks.ks` used
115+
`rsync --filter='-x security.selinux'`. ostree relabels `/var` only once
116+
at deploy-finalize (before `%post`), so the rsynced repo kept a wrong
117+
context → confined flatpak denied access to `/var/lib/flatpak/repo`.
118+
Bluefin does NOT strip; Bazzite strips but then `restorecon`s. Margine did
119+
neither's safe half.
120+
2. **Bake rsync targeted the per-deployment `.0/var`**, which the booted
121+
system never mounts as `/var` (runtime `/var` is the stateroot var) —
122+
plausibly shadowing the bake. (Most-disputed of the four; upstream uses
123+
the same target but ALSO bakes into the committed image, which Margine
124+
does not.)
125+
3. **No `disable-fedora-flatpak.ks`** (both upstreams ship it) — Fedora's
126+
`flatpak-add-fedora-repos` can half-initialize/clobber the system repo.
127+
4. **`flatpak-preinstall.service` had a brittle 3-strike lockout** — one
128+
transient first-boot failure left it permanently `failed`, so the
129+
download fallback never recovered.
130+
131+
### Resolution (PR #222 — align to Bluefin/Bazzite)
132+
- `install-flatpaks.ks`: target the real mounted runtime `/var`
133+
(`/mnt/sysimage/var`), drop the SELinux label-strip, add a loud
134+
`MARGINE-BAKE-OK/FAIL` marker.
135+
- New `disable-fedora-flatpak.ks` (mask `flatpak-add-fedora-repos`) BEFORE
136+
the bake; new `flatpak-restore-selinux-labels.ks` (`restorecon`) AFTER it.
137+
- `flatpak-preinstall.service` drop-in: `StartLimitIntervalSec=0` +
138+
ExecStartPre ensure-flathub + `flatpak repair` → self-healing fallback.
139+
140+
**Honest status:** these are upstream-alignment fixes (verified divergences),
141+
not yet confirmed against a reproduced install. The definitive confirmation
142+
is the real-install CI gate (below).
143+
144+
---
145+
146+
## Cross-cutting: why both shipped, and the CI gaps
147+
148+
- **The dev host masks both bugs.** It has Secure Boot off, a real/normal
149+
UART (so `console=ttyS0` doesn't stall), and its Flatpaks came from the
150+
download fallback (not the bake). Never trust the dev host to validate
151+
either path.
152+
- **No CI ever did a real ISO install + first boot.** `smoke-boot` builds a
153+
qcow2 directly from the OCI image (skips Anaconda + the kickstart);
154+
`build-disk` only boots the LIVE session (where `/var/lib/flatpak` is a
155+
read-only mount that looks fine). `install-flatpaks.ks` had literally never
156+
run end-to-end in CI.
157+
- **A truncated local ISO sent the first repro attempts down a rabbit hole.**
158+
A `curl` that died at 6.5/7.9 GB produced an ISO that failed to boot in
159+
every local QEMU configuration — mistaken for OVMF / `-kernel` problems.
160+
The `-kernel/-initrd` boot method is fine; the dev host has 4M OVMF.
161+
- **The boot-test's own bug:** it loop-mounted the ISO with `sudo` then
162+
`cp`'d as the runner user → `Permission denied`. Fixed to extract with
163+
`xorriso` (no mount/sudo) in PR #221's follow-up.
164+
165+
### Regression guards added
166+
- **Static guard** (`.github/scripts/check-flatpak-fixes.sh`, run in `lint`):
167+
asserts all four Flatpak invariants + the no-`console=ttyS0` invariant stay
168+
in place. Cheap, immediate.
169+
- **Real-install gate** (planned): a `build-disk.yml` job that boots the ISO,
170+
triggers an automated Anaconda install (a dormant `anaconda --kickstart`
171+
service gated by a CI-only `margine.autoinstall` karg — `inst.ks`/OEMDRV do
172+
NOT work on this live ISO, its initrd has no anaconda-dracut modules), then
173+
offline-verifies the installed disk via `qemu-nbd`
174+
(`/var/lib/flatpak/repo/refs/remotes/flathub` present, app count, SELinux
175+
labels). This reproduces + permanently guards the class.
176+
177+
### Lessons
178+
- A knob added for **CI/dev convenience** (the serial console) broke **real
179+
hardware**. Inject test-only knobs at test time, never ship them.
180+
- "Works on our hardware + in CI" is not "works on arbitrary hardware":
181+
mini-PCs with phantom ACPI/firmware devices are a real, common class.
182+
- Atomic/ostree `/var` semantics + SELinux relabel timing are subtle; mirror
183+
what two working upstreams (Bluefin, Bazzite) do rather than inventing a
184+
third way.

0 commit comments

Comments
 (0)