From ce9579f767da9dfa66bc8862df6df50edb0a571c Mon Sep 17 00:00:00 2001 From: "prompt.ac/@jeffrey" Date: Thu, 24 Sep 2026 16:08:10 -0700 Subject: [PATCH] ac-os chromebook stub: re-probe wifi and SOF audio with firmware from the stick On the depthcharge path the built-in drivers probe at ~0.7 s while the root is still the embedded stub, so iwlwifi and the SOF DSP fail their firmware loads and give up before the real initramfs is unpacked. The Lenovo 500e booted with no wifi and no sound card, so no TTS greeting and no connection. After unpacking, the stub now points firmware_class.path at the unpacked tree, unbinds and rebinds the Intel/Realtek wifi and sof-audio PCI drivers, and waits up to 8 s for a wl* interface and a sound card before switch_root. --- fedac/native/docs/chromebook-boot.md | 9 +++++++ fedac/native/initramfs-stub/init | 36 ++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/fedac/native/docs/chromebook-boot.md b/fedac/native/docs/chromebook-boot.md index e085a98d14..9121915bd2 100644 --- a/fedac/native/docs/chromebook-boot.md +++ b/fedac/native/docs/chromebook-boot.md @@ -31,6 +31,15 @@ and `config.json`, unpacks the real initramfs into a tmpfs and `switch_root`s into it. From there boot is identical to the UEFI path, including the inscription baked into `initramfs.cpio.gz` at flash time. +Built-in drivers probe while the stub is still the whole root, so Intel +wifi (iwlwifi) and the SOF audio DSP fail their firmware loads at ~0.7 s and +give up. After unpacking, the stub points `firmware_class.path` at the +unpacked tree, unbinds and rebinds those PCI drivers, and waits up to 8 s +for a `wl*` interface and a sound card before switching root. Without this +the Lenovo 500e came up with no wifi and no speaker (2026-09-24). The +regulatory database is still loaded only once by cfg80211 and stays on +the world default on this path. + On UEFI boots the firmware-supplied initrd is unpacked over the embedded one, so its `/init` replaces the stub and the stub never runs. `/proc/cmdline` contains `ac.boot=chromeos` only on the depthcharge path; diff --git a/fedac/native/initramfs-stub/init b/fedac/native/initramfs-stub/init index 1e78dac0c4..e75a2d43f0 100755 --- a/fedac/native/initramfs-stub/init +++ b/fedac/native/initramfs-stub/init @@ -65,6 +65,42 @@ fi cd / umount /boot 2>/dev/null +# Built-in drivers probed while this stub was the whole root, so anything +# that wanted firmware (Intel wifi, SOF audio DSP, Realtek wifi) failed at +# ~0.7 s with "Direct firmware load failed" and gave up. Point the kernel's +# firmware search path at the unpacked tree, re-probe those drivers, and +# wait for the results so ac-native finds a sound card and a wlan the +# moment it starts. The path entry is left in place: after switch_root it +# is a dead directory the loader skips before its normal /lib/firmware. +if [ -w /sys/module/firmware_class/parameters/path ]; then + echo /newroot/lib/firmware > /sys/module/firmware_class/parameters/path + want_wlan=0; want_snd=0 + for drv in /sys/bus/pci/drivers/iwlwifi /sys/bus/pci/drivers/rtw88_* \ + /sys/bus/pci/drivers/rtw89_* /sys/bus/pci/drivers/ath1* \ + /sys/bus/pci/drivers/mt76* /sys/bus/pci/drivers/sof-audio-pci-intel-*; do + [ -d "$drv" ] || continue + for dev in "$drv"/0000:*; do + [ -e "$dev" ] || continue + d=$(basename "$dev") + case "$drv" in *sof-audio*) want_snd=1 ;; *) want_wlan=1 ;; esac + echo "$d" > "$drv/unbind" 2>/dev/null + echo "$d" > "$drv/bind" 2>/dev/null + say "re-probed $d ($(basename "$drv")) with firmware from the stick" + done + done + # Both drivers load firmware asynchronously after bind; give them ~8 s. + waited=0 + while [ "$waited" -lt 40 ]; do + ok=1 + if [ "$want_wlan" = 1 ]; then ls /sys/class/net 2>/dev/null | grep -q '^wl' || ok=0; fi + if [ "$want_snd" = 1 ]; then grep -q '^ *[0-9]' /proc/asound/cards 2>/dev/null || ok=0; fi + [ "$ok" = 1 ] && break + waited=$((waited + 1)) + sleep 0.2 + done + say "firmware re-probe done after $((waited / 5)).$((waited % 5 * 2)) s (wlan wanted=$want_wlan, sound wanted=$want_snd): $(ls /sys/class/net 2>/dev/null | tr '\n' ' ')/ $(grep -c '^ *[0-9]' /proc/asound/cards 2>/dev/null || echo 0) sound card(s)" +fi + # Hand the live mounts to the new root, then pivot. The real /init mounts # proc/sys/dev itself and tolerates them already being there. mount -o move /dev /newroot/dev 2>/dev/null -- 2.51.2