ALSA =y en linux-metal (b3:613bca15): HDA legacy + codecs (lo que emula QEMU y usan las máquinas pre-SOF), SOF para TigerLake (el laptop del target NO suena por la ruta legacy: Intel movió el audio al DSP) y SND_USB_AUDIO. Todo =y porque el producto es monolítico. ⚠ Falta inyectar el FIRMWARE de SOF en la imagen (intel/sof/*.ri, sof-tplg/*.tplg), igual que metal-firmware.sh hace con los tgl_* de i915: sin blobs el driver carga y falla. FUNCIONÓ LA MITAD: en la VM `/dev/snd` ya trae controlC0 + pcmC0D0p/c y /sys/class/sound lista card0. El kernel detecta la tarjeta. Pero wpctl sigue con `Devices:` vacío. **Y LA CAUSA ES ESTRUCTURAL, no una propiedad que falte.** `get_card_nr` de SPA (alsa-udev.c:178-183) sólo acepta el device CARD —`/sys/.../sound/card0`—, que es un device de CLASE: sin major:minor, sin nodo en /dev. Y `udev_enumerate_scan_devices` de libudev-zero recorre EXCLUSIVAMENTE /sys/dev/block y /sys/dev/char (udev_enumerate.c:281), o sea sólo devices CON nodo; el udev real enumera /sys/class entero. **El device que SPA necesita nunca entra en la enumeración**: no hay guarda que sacar, falta la mitad del espacio de búsqueda. Salidas: (a) enseñarle a libudev-zero a recorrer /sys/class —radio 51 sellados— o (b) empaquetar eudev. Es decisión de arquitectura, no parche. CORRIJO ALGO QUE ESCRIBÍ ANTES: el parche `pipewire-sound-initialized.patch` se hizo creyendo que SOUND_INITIALIZED era el bloqueo, y NO lo era — con el parche aplicado el resultado no cambió. Se conserva porque la incompatibilidad que describe es real (sin udevd nadie pone esa propiedad y SPA descartaría toda tarjeta en cuanto la enumeración funcione), pero su prosa ahora empieza avisando que no es la solución. Sacarlo del camino importa: dejarlo presentado como el arreglo mandaría al próximo a buscar en el lugar equivocado. Dos arreglos de andamiaje que costaron un ciclo cada uno: - **`-nic none` por defecto.** Agregar la tarjeta de sonido CORRIÓ LAS RUTAS PCI, la entrada de disco cacheada en las VARS de OVMF dejó de coincidir, y la firmware se fue al orden por defecto: PXE v4, PXE v6, HTTP… minutos de timeouts. Con un TIMEOUT corto eso se lee como «la VM no arrancó» y el serial sólo dice `PXE-E16: No valid offer received`. - El filtro del log de wireplumber era `alsa|udev|sound|card|monitor` con `tail -40`, y se llenó de bluez/v4l2/libcamera —tres monitores que avisan que su plugin no está— dejando fuera justo las líneas de ALSA. **Un filtro ancho con cola corta es peor que ninguno.** Ahora filtra `alsa` y además copia el log entero a la raíz ext4 (tmpfs muere con la VM). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
82 lines
4.1 KiB
Bash
Executable File
82 lines
4.1 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# run-qemu-desktop.sh — arranca la imagen KDE en QEMU (virtio-gpu + software GL) de forma REPRODUCIBLE.
|
|
# Antes era un comando ad-hoc. Por defecto headless (DISPLAY=none) para diagnóstico por serial sin
|
|
# interferir con la sesión mirada del laptop; DISP=gtk para ver la ventana (necesita DISPLAY=:0 Xwayland,
|
|
# y cada restart de mirada mata la ventana).
|
|
#
|
|
# scripts/kde/run-qemu-desktop.sh # headless, serial → work/qemu-desktop-serial.log
|
|
# DISP=gtk scripts/kde/run-qemu-desktop.sh # ventana gráfica (virtio-gpu por gtk)
|
|
# TIMEOUT=90 scripts/kde/run-qemu-desktop.sh # mata QEMU a los 90s (diagnóstico automático)
|
|
set -euo pipefail
|
|
ROOT="$(cd "$(dirname "$0")/../.." && pwd)"; cd "$ROOT"
|
|
|
|
IMG="${IMG:-work/hammer-kde-qemu.img}"
|
|
SERIAL="${SERIAL:-work/qemu-desktop-serial.log}"
|
|
OVMF_CODE="${OVMF_CODE:-/usr/share/edk2/x64/OVMF_CODE.4m.fd}"
|
|
OVMF_VARS_SRC="${OVMF_VARS_SRC:-/usr/share/edk2/x64/OVMF_VARS.4m.fd}"
|
|
VARS="${VARS:-work/qemu-desktop-OVMF_VARS.fd}"
|
|
DISP="${DISP:-none}"
|
|
MEM="${MEM:-4G}"
|
|
SMP="${SMP:-4}"
|
|
|
|
[ -r "$IMG" ] || { echo "falta $IMG — corré scripts/kde/qemu-desktop-image.sh" >&2; exit 1; }
|
|
[ -r "$OVMF_CODE" ] || { echo "falta OVMF_CODE ($OVMF_CODE)" >&2; exit 1; }
|
|
# copia escribible de las VARS (pflash necesita rw; la del sistema es read-only)
|
|
[ -r "$VARS" ] || cp "$OVMF_VARS_SRC" "$VARS"
|
|
|
|
case "$DISP" in
|
|
gtk) DISPLAY_ARGS=(-display gtk -device virtio-gpu-pci) ;;
|
|
none) DISPLAY_ARGS=(-display none -device virtio-gpu-pci) ;;
|
|
*) DISPLAY_ARGS=(-display "$DISP" -device virtio-gpu-pci) ;;
|
|
esac
|
|
|
|
# serial nuevo cada corrida (el diagnóstico depende de que no se mezcle con boots viejos)
|
|
: > "$SERIAL"
|
|
|
|
QEMU_ARGS=(
|
|
-machine q35 -accel kvm -cpu host
|
|
-m "$MEM" -smp "$SMP"
|
|
-vga none # virtio-gpu-pci (abajo) es el ÚNICO display: sin esto QEMU añade una VGA estándar por
|
|
# defecto y OVMF pinta el GOP ahí ⇒ simpledrm (card1) muestra el framebuffer EFI y kwin
|
|
# pinta en virtio-gpu (card0, otro device que no se ve) ⇒ pantalla congelada en TianoCore.
|
|
# Con -vga none, OVMF usa virtio-gpu ⇒ virtio-gpu-DRM expulsa simpledrm ⇒ un solo output.
|
|
-drive if=pflash,format=raw,unit=0,file="$OVMF_CODE",readonly=on
|
|
-drive if=pflash,format=raw,unit=1,file="$VARS"
|
|
-drive file="$IMG",format=raw,if=virtio
|
|
"${DISPLAY_ARGS[@]}"
|
|
-serial "file:$SERIAL"
|
|
-monitor "unix:${MON:-work/qemu-monitor.sock},server,nowait"
|
|
-no-reboot
|
|
)
|
|
|
|
# AUDIO=1 (default): darle a la VM una tarjeta de sonido EMULADA. No es para oír nada —el backend es
|
|
# `none`, que descarta las muestras— sino para que HAYA UN DISPOSITIVO QUE ENUMERAR.
|
|
#
|
|
# Sin esto, `wpctl status` sale con «Devices:» vacío y un único sink `auto_null`, y ese resultado es
|
|
# AMBIGUO: se lee igual si wireplumber funciona sobre una VM sin hardware que si wireplumber no
|
|
# funciona. Con una ich9-intel-hda emulada, el árbol de /sys/class/sound existe y la respuesta
|
|
# distingue las dos cosas. AUDIO=0 para volver al caso sin tarjeta.
|
|
if [ "${AUDIO:-1}" = 1 ]; then
|
|
QEMU_ARGS+=(-audiodev none,id=snd0 -device ich9-intel-hda -device hda-duplex,audiodev=snd0)
|
|
fi
|
|
|
|
# NET=none (default): SIN tarjeta de red. No es sólo ahorro — QEMU añade una e1000 por defecto, y OVMF
|
|
# la usa para crear entradas de arranque PXE/HTTP (IPv4 e IPv6). Cuando la entrada de disco que OVMF
|
|
# tenía cacheada en sus VARS deja de coincidir —y basta AGREGAR UN DISPOSITIVO PCI, como la tarjeta de
|
|
# sonido de arriba, para que las rutas se corran— la firmware cae al orden por defecto y se pasa un
|
|
# par de minutos en timeouts de PXE antes de llegar al disco. Con un TIMEOUT corto eso se ve como
|
|
# «la VM no arrancó», y el serial sólo muestra `PXE-E16: No valid offer received`. Pasó de verdad.
|
|
# Este escritorio no necesita red; `NET=user` si algún día hace falta.
|
|
if [ "${NET:-none}" = none ]; then
|
|
QEMU_ARGS+=(-nic none)
|
|
fi
|
|
|
|
echo "==> QEMU (DISP=$DISP, serial=$SERIAL)"
|
|
echo " imagen: $IMG"
|
|
if [ -n "${TIMEOUT:-}" ]; then
|
|
echo " TIMEOUT=${TIMEOUT}s (auto-kill)"
|
|
exec timeout --signal=KILL "${TIMEOUT}" qemu-system-x86_64 "${QEMU_ARGS[@]}"
|
|
else
|
|
exec qemu-system-x86_64 "${QEMU_ARGS[@]}"
|
|
fi
|