diff --git a/recipes/linux-metal-dual.toml b/recipes/linux-metal-dual.toml index 869ac911..4ceda80a 100644 --- a/recipes/linux-metal-dual.toml +++ b/recipes/linux-metal-dual.toml @@ -73,6 +73,7 @@ scripts/config -d MODULE_SIG -d MODULE_SIG_ALL -d DEBUG_INFO_BTF -d DEBUG_INFO - -e ISO9660_FS -e JOLIET -e DEVTMPFS \ -e WLAN -e WIRELESS -e CFG80211 -e MAC80211 -e RFKILL \ -e WLAN_VENDOR_INTEL -e IWLWIFI -e IWLMVM -e IWLDVM \ + -e WLAN_VENDOR_ATH -e ATH_COMMON -e ATH10K -e ATH10K_PCI \ -e ETHERNET -e NET_VENDOR_INTEL -e E1000 -e E1000E -e IGB -e IGC \ -e NET_VENDOR_REALTEK -e R8169 -e NET_VENDOR_BROADCOM -e TG3 \ -e USB_NET_DRIVERS -e USB_USBNET -e USB_NET_CDCETHER -e USB_NET_CDC_NCM -e USB_NET_RNDIS_HOST \ diff --git a/scripts/cosmic/metal-desktop-image.sh b/scripts/cosmic/metal-desktop-image.sh index 8347bd2d..b21515c5 100755 --- a/scripts/cosmic/metal-desktop-image.sh +++ b/scripts/cosmic/metal-desktop-image.sh @@ -174,10 +174,28 @@ cat > "$MERGED/usr/bin/cosmic-diag" <<'DIAG' export PATH=/usr/bin:/bin:/usr/sbin:/sbin L=/var/log/cosmic mkdir -p "$L" -echo "== cosmic-diag: corriendo la sesión y capturando todo en $L (unos 60s) ==" +echo "== cosmic-diag: corriendo la sesión y capturando todo en $L ==" /bin/busybox dmesg > "$L/dmesg-antes.txt" 2>&1 cosmic-start > "$L/run.txt" 2>&1 & -sleep 50 +# ⚠ NO usar un `sleep` fijo. La 1ª versión esperaba 50s y en el OptiPlex 3060 la sesión tarda ~105s +# en llegar al compositor (seatd, bus, logind, pipewire, wireplumber, cada uno con su espera) ⇒ el +# dmesg «después» se capturaba ANTES de que cosmic-comp arrancara, salía byte a byte idéntico al de +# antes, y el viaje se gastaba sin dato. Ahora se espera al HECHO, no al reloj: que cosmic-comp +# aparezca y después desaparezca. Ésa es la ventana donde el kernel diría un segfault. +vivo() { for c in /proc/[0-9]*/comm; do [ "$(cat "$c" 2>/dev/null)" = cosmic-comp ] && return 0; done; return 1; } +i=0; visto=0 +while [ $i -lt 72 ]; do # 72 × 5s = 6 min de techo + if vivo; then + [ $visto = 0 ] && echo " cosmic-comp vivo (t=$((i*5))s), esperando a que muera o se estabilice" + visto=1 + elif [ $visto = 1 ]; then + echo " cosmic-comp DESAPARECIÓ (t=$((i*5))s) — capturando dmesg" + break + fi + i=$((i + 1)); sleep 5 +done +[ $visto = 0 ] && echo " ⚠ cosmic-comp nunca apareció en $((i*5))s — capturo igual" +sleep 2 /bin/busybox dmesg > "$L/dmesg-despues.txt" 2>&1 /bin/busybox sync echo "== listo. Lo que importa: ==" @@ -190,6 +208,71 @@ echo "== evidencia completa en $L — apagá y traé el USB ==" DIAG chmod 0755 "$MERGED/usr/bin/cosmic-diag" +# ── WiFi: la QCA9377 del OptiPlex, y por qué hace falta un re-probe ────────────────────────────── +# `pci 0000:02:00.0: [168c:0042]` = Qualcomm Atheros QCA9377, que va por `ath10k`. El kernel ahora lo +# lleva compilado dentro (MODULES está desactivado en esta receta), y ahí aparece un problema de +# ORDEN: un driver builtin prueba el dispositivo a los ~5 s y pide su firmware, pero el rootfs recién +# se monta a los ~13 s ⇒ `Direct firmware load failed -2` y la tarjeta queda muda para siempre. No hay +# módulo que cargar después. La salida es forzar un RE-PROBE del dispositivo PCI cuando /lib/firmware +# ya existe: `remove` + `rescan`. Es el mismo tipo de carrera que la del initramfs con el USB. +FWATH="${FWATH:-/usr/lib/firmware/ath10k}" +if [ -d "$FWATH/QCA9377" ]; then + n=0 + for f in "$FWATH"/QCA9377/hw1.0/*.bin*; do + [ -r "$f" ] || continue + b="$(basename "$f")"; d="$MERGED/lib/firmware/ath10k/QCA9377/hw1.0" + mkdir -p "$d" + case "$b" in + *.zst) zstd -qdf "$f" -o "$d/${b%.zst}" 2>/dev/null && n=$((n+1)) ;; + *) cp -a "$f" "$d/" && n=$((n+1)) ;; + esac + done + echo "==> firmware ath10k/QCA9377: $n blobs" +else + echo " ⚠ sin $FWATH/QCA9377 — el WiFi de esa máquina no va a levantar" +fi +cat > "$MERGED/usr/bin/wifi-up" <<'WIFI' +#!/bin/sh +# wifi-up — conecta la WiFi y muestra la IP para entrar por SSH. +export PATH=/usr/bin:/bin:/usr/sbin:/sbin +SSID="$1"; PSK="$2" +[ -n "$SSID" ] || { echo "uso: wifi-up "; exit 1; } +# Re-probe: ath10k pidió su firmware antes de que existiera /lib/firmware (ver el comentario de la +# imagen). Sin esto la tarjeta no aparece como interfaz aunque el driver esté. +for d in /sys/bus/pci/devices/*; do + [ "$(cat "$d/vendor" 2>/dev/null)" = "0x168c" ] || continue + echo "re-probando $(basename "$d") para que ath10k reintente el firmware…" + echo 1 > "$d/remove" 2>/dev/null; sleep 2 + echo 1 > /sys/bus/pci/rescan 2>/dev/null; sleep 4 +done +IF="" +for i in /sys/class/net/*; do + case "$(basename "$i")" in wlan*|wlp*) IF="$(basename "$i")"; break ;; esac +done +[ -n "$IF" ] || { echo "no apareció interfaz wifi. Mirá: dmesg | grep -i ath10k"; exit 1; } +echo "interfaz: $IF" +ip link set "$IF" up +printf 'network={\n\tssid="%s"\n\tpsk="%s"\n}\n' "$SSID" "$PSK" > /tmp/wpa.conf +wpa_supplicant -B -i "$IF" -c /tmp/wpa.conf -Dnl80211 || { echo "wpa_supplicant falló"; exit 1; } +sleep 6 +cat > /tmp/udhcpc.script <<'US' +#!/bin/sh +case "$1" in + bound|renew) + ifconfig "$interface" "$ip" netmask "${subnet:-255.255.255.0}" + [ -n "$router" ] && route add default gw "${router%% *}" dev "$interface" 2>/dev/null + [ -n "$dns" ] && { : > /etc/resolv.conf; for d in $dns; do echo "nameserver $d" >> /etc/resolv.conf; done; } + ;; +esac +exit 0 +US +chmod +x /tmp/udhcpc.script +udhcpc -i "$IF" -n -q -s /tmp/udhcpc.script +ip -4 addr show "$IF" | grep -w inet || echo "sin IPv4 — ¿clave correcta? wpa_cli status" +echo "== desde el laptop: ssh -i ~/.ssh/hammer-metal root@ ==" +WIFI +chmod 0755 "$MERGED/usr/bin/wifi-up" + # ── getty en tty1: el prompt TIENE que salir por la PANTALLA ──────────────────────────────────── # Lección del 1er viaje físico de KDE, que costó un USB quemado: el CMDLINE horneado es # `console=tty0 console=ttyS0,115200 …` y el kernel hace /dev/console = la ÚLTIMA `console=` ⇒ ttyS0.