250 líneas de comentario en 151 scripts. Control verificado: el diff no toca NI UNA línea que no empiece por #, y la sintaxis de los 151 pasa. El barrido saltea heredocs y cadenas triples, y el guardián DISPARÓ 3 veces: las tres eran el MOTD que el script escribe DENTRO de la imagen construida — texto del producto, no comentario del script. Se cambiaron aparte y a propósito, que es rebranding, no limpieza. Y el hallazgo caro: casaba contra , que es el TARGET de tracing — o sea el module_path!, o sea el nombre del crate. La etapa 4 lo movió a y el script quedó casando NADA. No fallaba: imprimía cero atribuciones, indistinguible de un log sin problemas. Comprobado con el binario (RUST_LOG=info sobre zlib), no deducido. Ahora acepta las dos, y tiene que seguir aceptándolas porque los logs viejos en disco dicen la vieja. Además 14 rutas de módulo en docs, que el barrido anterior no tocó porque no es frontera de palabra.
426 lines
23 KiB
Bash
426 lines
23 KiB
Bash
#!/usr/bin/env bash
|
|
# mirada-usb.sh — arma el ROOTFS live de mirada por SOFTWARE (mesa-swrast/softpipe, sin GPU driver ni
|
|
# firmware) para probar el compositor en GPU ajena (NVIDIA/AMD/lo-que-sea). Genérico: arranca sobre
|
|
# simpledrm (framebuffer EFI, anda en cualquier UEFI), virtio-gpu (VM) o nouveau-sin-accel.
|
|
#
|
|
# Es la ruta "uso normal" del HANDOFF-nvidia-mirada.md: valida el compositor SIN depender del driver.
|
|
# La aceleración real por nouveau (NVK/gallium-nouveau + GSP firmware) queda para una v2.
|
|
#
|
|
# Qué hace:
|
|
# 1) Rootfs SLIM: loader musl + busybox + .so runtime tomados de .dev-fs/alpine (la musl userland
|
|
# contra la que se construyeron los binarios), NO el 1.2G entero.
|
|
# 2) Hydrata los artefactos takana del stack gráfico + mirada desde el store (por hash).
|
|
# 3) Cierra el grafo DT_NEEDED: escanea los ELF, y toda .so que falte la trae de .dev-fs/alpine.
|
|
# 4) Escribe /sbin/init = lanzador (seatd + `mirada-compositor --drm --greeter`).
|
|
# 5) Empaqueta la imagen USB con el kernel linux-generic vía scripts/metal-usb-sdboot.sh.
|
|
#
|
|
# Uso: scripts/mirada-usb.sh # arma rootfs + imagen work/hammer-mirada-usb.img
|
|
# PACKAGE=0 scripts/mirada-usb.sh # sólo el rootfs (work/mirada-rootfs), sin imagen
|
|
# Quemar: sudo dd if=work/hammer-mirada-usb.img of=/dev/sdX bs=4M oflag=sync status=progress
|
|
set -euo pipefail
|
|
ROOT="$(cd "$(dirname "$0")/.." && pwd)"; cd "$ROOT"
|
|
|
|
STORE="${STORE:-./store}"
|
|
DEVFS="${DEVFS:-.dev-fs/alpine}"
|
|
RFS="${RFS:-work/mirada-rootfs}"
|
|
HAMMER="${TAKANA:-${HAMMER:-target/release/takana}}"
|
|
PACKAGE="${PACKAGE:-1}"
|
|
|
|
[ -d "$DEVFS" ] || { echo "no existe $DEVFS (corré scripts/bootstrap-devfs.sh)" >&2; exit 1; }
|
|
[ -x "$HAMMER" ] || { echo "no existe $HAMMER (cargo build --release)" >&2; exit 1; }
|
|
|
|
# --- artefactos del store a hydratar (hash explícito para los recién construidos; resto por nombre) ---
|
|
declare -A PIN=(
|
|
[mesa-swrast]=410e4fb9806598921048f492508725f55ee8475a1e9ef8ea2dc64f357154a0d9
|
|
[libxkbcommon]=cef7db4a82882ee942fef5e758344da67c9f3fce6b221610a7db9cb05bfb3b53
|
|
)
|
|
# Orden: libs primero, binarios mirada al final. Todos aportan .so o /usr/bin. El set sale del
|
|
# MANIFIESTO DE OBJETIVO (docs/state/targets.toml, perfil `escritorio-mirada`), que preserva el orden.
|
|
PKGS="$("$(dirname "$0")/targets.py" escritorio-mirada)"
|
|
|
|
resolve() { # nombre -> hash del store (pin si existe, si no el más reciente por mtime)
|
|
local n="$1"
|
|
if [ -n "${PIN[$n]:-}" ]; then echo "${PIN[$n]}"; return; fi
|
|
local d; d=$(ls -dt "$STORE"/*-"$n" 2>/dev/null | grep -E "\-$n\$" | head -1) || true
|
|
[ -n "$d" ] || { echo "" ; return; }
|
|
basename "$d" | sed "s/-$n\$//"
|
|
}
|
|
|
|
echo "==> rootfs slim en $RFS"
|
|
rm -rf "$RFS"; mkdir -p "$RFS"/{bin,sbin,usr/bin,usr/sbin,usr/lib,lib,etc,dev,proc,sys,run,tmp,root}
|
|
mkdir -p "$RFS"/usr/lib/dri "$RFS"/var/lib/hammer
|
|
|
|
# 1) loader musl + libc.so + .so runtime base desde el dev-fs
|
|
echo "==> base musl + runtime .so desde $DEVFS"
|
|
cp -aL "$DEVFS"/lib/ld-musl-x86_64.so.1 "$RFS"/lib/ 2>/dev/null || true
|
|
for so in libc.so libz.so.1 libzstd.so.1 libexpat.so.1 libffi.so.8 libstdc++.so.6 libgcc_s.so.1 libbz2.so.1 liblzma.so.5; do
|
|
f=$(find "$DEVFS" -name "$so" 2>/dev/null | head -1)
|
|
# -aL: DESREFERENCIA symlinks (libz.so.1→libz.so.1.3.2) ⇒ archivo real con el SONAME que pide NEEDED.
|
|
[ -n "$f" ] && cp -aL "$f" "$RFS"/usr/lib/ || true
|
|
done
|
|
|
|
# 2) busybox + applets
|
|
echo "==> busybox"
|
|
cp -a "$DEVFS"/bin/busybox "$RFS"/bin/busybox
|
|
for a in sh mount umount mkdir ln cp mv rm cat echo sleep ls ps kill chmod chown ip udhcpc dmesg mknod switch_root getty login setsid \
|
|
findfs blkid sync tee date uname free df head tail grep sed awk cut tr wc find md5sum dd stat readlink basename; do
|
|
ln -sf busybox "$RFS/bin/$a"
|
|
done
|
|
ln -sf /bin/busybox "$RFS/sbin/init.busybox"
|
|
|
|
# 3) hydratar el stack gráfico + mirada desde el store
|
|
echo "==> hydratando artefactos hammer"
|
|
for p in $PKGS; do
|
|
h=$(resolve "$p")
|
|
[ -n "$h" ] || { echo " ✗ $p — no está en el store" >&2; exit 1; }
|
|
"$HAMMER" --store "$STORE" hydrate "$h" --into "$RFS" --link static >/dev/null 2>&1
|
|
printf ' ✓ %-18s %s\n' "$p" "${h:0:12}"
|
|
done
|
|
|
|
# 4) cierre DT_NEEDED: toda .so requerida y ausente, traerla del dev-fs (desreferenciada).
|
|
# Varias rondas fijas (una .so nueva puede arrastrar NEEDED propios). Todo guardado del set -e.
|
|
echo "==> cerrando el grafo DT_NEEDED (faltantes ← $DEVFS)"
|
|
libdirs=("$RFS/usr/lib" "$RFS/lib" "$RFS/lib64" "$RFS/usr/lib/dri")
|
|
have_so() { local s="$1" d; for d in "${libdirs[@]}"; do [ -e "$d/$s" ] && return 0; done; return 1; }
|
|
list_elf() { find "$RFS" -type f 2>/dev/null | while read -r f; do head -c4 "$f" 2>/dev/null | grep -q ELF && echo "$f"; done; }
|
|
needed_sonames() { local e; list_elf | while read -r e; do readelf -d "$e" 2>/dev/null | awk -F'[][]' '/NEEDED/{print $2}'; done | sort -u; }
|
|
for round in 1 2 3; do
|
|
falto=0
|
|
for so in $(needed_sonames); do
|
|
[ -n "$so" ] || continue
|
|
have_so "$so" && continue
|
|
f=$(find "$DEVFS" -name "$so" 2>/dev/null | head -1 || true)
|
|
if [ -n "$f" ]; then cp -aL "$f" "$RFS/usr/lib/" && echo " + $so"; else echo " ! FALTA (no en dev-fs): $so"; falto=1; fi
|
|
done
|
|
[ "$falto" -eq 0 ] && break
|
|
done
|
|
: <<'DEADCODE'
|
|
DEADCODE
|
|
|
|
# 5) config mínima: passwd/group/pam + ld.so path
|
|
echo "==> config (passwd/group/pam)"
|
|
cat > "$RFS/etc/passwd" <<'EOF'
|
|
root:x:0:0:root:/root:/bin/sh
|
|
EOF
|
|
cat > "$RFS/etc/group" <<'EOF'
|
|
root:x:0:
|
|
video:x:27:root
|
|
input:x:28:root
|
|
seat:x:29:root
|
|
EOF
|
|
mkdir -p "$RFS/etc/pam.d"
|
|
# PAM permisivo: el greeter RENDERIZA antes de autenticar; con esto un login vacío/root pasa.
|
|
cat > "$RFS/etc/pam.d/other" <<'EOF'
|
|
auth sufficient pam_permit.so
|
|
account sufficient pam_permit.so
|
|
password sufficient pam_permit.so
|
|
session sufficient pam_permit.so
|
|
EOF
|
|
for svc in login mirada mirada-greeter system-auth; do cp "$RFS/etc/pam.d/other" "$RFS/etc/pam.d/$svc"; done
|
|
# ld musl busca en /usr/lib y /lib por defecto; dejamos un ld-musl path explícito por las dudas.
|
|
mkdir -p "$RFS/etc"
|
|
# musl REEMPLAZA su path por defecto con este fichero ⇒ hay que listar TODOS los dirs, incl. /lib64
|
|
# (linux-pam instala ahí) y /usr/lib/dri (drivers mesa).
|
|
printf '/usr/lib\n/lib\n/lib64\n/usr/lib/dri\n' > "$RFS/etc/ld-musl-x86_64.path"
|
|
|
|
# 5b) DATOS XKB (xkeyboard-config): libxkbcommon compila el keymap por defecto (evdev/pc105/us) desde
|
|
# /usr/share/X11/xkb; sin estos datos xkb_keymap_new falla y el compositor SEGFAULTEA en
|
|
# libxkbcommon. Son datos de texto/XML AGNÓSTICOS de arquitectura ⇒ los tomamos del host.
|
|
# (TODO soberanía: recipes/xkeyboard-config.toml — hoy no existe; para la imagen de test basta.)
|
|
XKB_SRC="${XKB_SRC:-/usr/share/X11/xkb}"
|
|
if [ -d "$XKB_SRC" ]; then
|
|
echo "==> datos XKB (xkeyboard-config) ← $XKB_SRC"
|
|
mkdir -p "$RFS/usr/share/X11"
|
|
cp -aL "$XKB_SRC" "$RFS/usr/share/X11/xkb"
|
|
else
|
|
echo " ⚠ no encuentro datos XKB en $XKB_SRC — el compositor crasheará en libxkbcommon" >&2
|
|
fi
|
|
|
|
# 5c) STACK GL/VULKAN por SOFTWARE + nouveau — de Alpine edge (musl, mismo libLLVM que el dev-fs).
|
|
# Por qué NO la mesa-swrast de takana: su softpipe basta para el COMPOSITOR, pero el greeter (wgpu)
|
|
# necesita un GL/Vulkan más completo. La mesa 26.1.1 de Alpine trae:
|
|
# · llvmpipe (swrast_dri.so + libgallium + libLLVM.so.22) → software GL robusto (compositor),
|
|
# · lavapipe (libvulkan_lvp.so + ICD) → software Vulkan (backend primario de wgpu),
|
|
# · nouveau_dri.so → GL por HARDWARE en la NVIDIA (si nouveau bindea con firmware GSP).
|
|
# Es la vía pragmática de la imagen de TEST (deuda de soberanía: build LLVM+mesa+NVK desde fuente).
|
|
# El greeter/Vello igual EXIGE shaders float16 ⇒ su login sólo pinta con GPU real (ver init).
|
|
MESAROOT="${MESAROOT:-work/alpine-mesa-root}"
|
|
if [ ! -e "$MESAROOT/usr/lib/libgallium-26.1.1.so" ]; then
|
|
echo "==> bajando mesa+lavapipe de Alpine edge (apk) → $MESAROOT"
|
|
APK="$DEVFS/sbin/apk"; ALD="$DEVFS/lib/ld-musl-x86_64.so.1"
|
|
rm -rf "$MESAROOT"; mkdir -p "$MESAROOT"
|
|
"$ALD" --library-path "$DEVFS/usr/lib:$DEVFS/lib" "$APK" add --root "$PWD/$MESAROOT" --initdb --usermode --no-cache \
|
|
--repository https://dl-cdn.alpinelinux.org/alpine/edge/main \
|
|
--repository https://dl-cdn.alpinelinux.org/alpine/edge/community \
|
|
--arch x86_64 --allow-untrusted \
|
|
mesa-dri-gallium mesa-egl mesa-gles mesa-gbm mesa-vulkan-swrast vulkan-loader >/dev/null 2>&1 \
|
|
|| { echo " ✗ apk falló (¿red?); no puedo bajar mesa" >&2; exit 1; }
|
|
fi
|
|
echo "==> overlay mesa+lavapipe en el rootfs"
|
|
cp -aL "$MESAROOT"/usr/lib/*.so* "$RFS/usr/lib/" 2>/dev/null || true
|
|
for sub in dri gbm; do
|
|
[ -d "$MESAROOT/usr/lib/$sub" ] && { mkdir -p "$RFS/usr/lib/$sub"; cp -aL "$MESAROOT/usr/lib/$sub/"*.so "$RFS/usr/lib/$sub/" 2>/dev/null || true; }
|
|
done
|
|
mkdir -p "$RFS/usr/share/vulkan/icd.d"
|
|
cp -aL "$MESAROOT"/usr/share/vulkan/icd.d/*.json "$RFS/usr/share/vulkan/icd.d/" 2>/dev/null || true
|
|
[ -d "$MESAROOT/usr/share/drirc.d" ] && cp -aL "$MESAROOT/usr/share/drirc.d" "$RFS/usr/share/" 2>/dev/null || true
|
|
rm -f "$RFS/usr/lib/libgcc_s.so" # symlink glibc espurio (el musl .so.1 sí está)
|
|
# cerrar deps de los drivers/ICD nuevos ← alpine-root + dev-fs
|
|
for round in 1 2 3; do
|
|
for so in $(needed_sonames); do
|
|
[ -n "$so" ] || continue
|
|
have_so "$so" && continue
|
|
f=$(find "$MESAROOT/usr/lib" "$DEVFS" -name "$so" 2>/dev/null | grep -v ld-linux | head -1 || true)
|
|
[ -n "$f" ] && cp -aL "$f" "$RFS/usr/lib/" && echo " + $so" || true
|
|
done
|
|
done
|
|
|
|
# 5c-bis) libudev = SIEMPRE el de libudev-zero. El apk de mesa arrastra `eudev-libs` y el overlay de
|
|
# arriba (`cp *.so*`) PISA el libudev.so.1 de libudev-zero con el de eudev. Sin udevd corriendo, el
|
|
# libudev de eudev enumera CERO dispositivos de entrada (no hay ID_INPUT sin la db de udevd) y
|
|
# libinput los ignora EN SILENCIO ⇒ pantalla viva, teclado y mouse muertos. Es EXACTAMENTE lo que
|
|
# pasó en el tester NVIDIA (2026-07-16); reproducido y verificado A/B en QEMU (usb-kbd: eudev = 0
|
|
# dispositivos; libudev-zero = 5 y Ctrl+Alt+BackSpace corta el compositor). La GPU no lo delata:
|
|
# smithay la encuentra por syspath, sin propiedades udev — por eso "grafica bien" no salva al input.
|
|
UZ=$(resolve libudev-zero)
|
|
[ -n "$UZ" ] || { echo "✗ libudev-zero no está en el store" >&2; exit 1; }
|
|
echo "==> libudev.so.1 ← libudev-zero (pisa el de eudev que arrastró el apk de mesa)"
|
|
rm -f "$RFS/usr/lib/libudev.so.1" "$RFS/usr/lib/libudev.so.1."* # el de eudev + sus versionados (.so.1.6.3)
|
|
cp -L "$STORE/$UZ-libudev-zero/usr/lib/libudev.so.1" "$RFS/usr/lib/libudev.so.1"
|
|
chmod 755 "$RFS/usr/lib/libudev.so.1"
|
|
cmp -s "$STORE/$UZ-libudev-zero/usr/lib/libudev.so.1" "$RFS/usr/lib/libudev.so.1" \
|
|
|| { echo "✗ el libudev.so.1 del rootfs NO es el de libudev-zero — input muerto garantizado" >&2; exit 1; }
|
|
|
|
# 5d) FIRMWARE nouveau (aceleración 3D). Pascal/Maxwell2 (GP10x/GM20x) piden los blobs firmados de
|
|
# ctxsw (gr/) + acr/sec2 para dar GL por hardware; sin ellos nouveau da display pero NO 3D ⇒ el
|
|
# greeter caería a software (sin float16). Turing+ (RTX) piden ADEMÁS gsp/. CHIP=gp106 para la GTX
|
|
# 1060. FW_SRC = árbol linux-firmware del host (o pasá el tuyo). NO es soberano (blob firmado NVIDIA).
|
|
CHIP="${CHIP:-gp106}"
|
|
FW_SRC="${FW_SRC:-/lib/firmware}"
|
|
if [ -n "$CHIP" ] && [ -d "$FW_SRC/nvidia/$CHIP" ]; then
|
|
echo "==> firmware nouveau nvidia/$CHIP ← $FW_SRC"
|
|
mkdir -p "$RFS/lib/firmware/nvidia"
|
|
cp -aL "$FW_SRC/nvidia/$CHIP" "$RFS/lib/firmware/nvidia/$CHIP"
|
|
# DESCOMPRIMIR .bin.zst/.xz → .bin: el request_firmware de nouveau busca `.bin`; el kernel sólo
|
|
# descomprime al vuelo si tiene FW_LOADER_COMPRESS (incierto en linux-generic). Descomprimir asegura.
|
|
find "$RFS/lib/firmware/nvidia/$CHIP" -name '*.zst' -exec sh -c 'zstd -q -d -f "$1" && rm -f "$1"' _ {} \; 2>/dev/null || true
|
|
find "$RFS/lib/firmware/nvidia/$CHIP" -name '*.xz' -exec sh -c 'xz -q -d -f "$1"' _ {} \; 2>/dev/null || true
|
|
elif [ -n "$CHIP" ]; then
|
|
echo " ⚠ no encuentro firmware nvidia/$CHIP en $FW_SRC — nouveau no dará 3D (greeter caerá a sw)" >&2
|
|
fi
|
|
|
|
# 6) /sbin/init = lanzador de mirada (software)
|
|
echo "==> lanzador /sbin/init"
|
|
cat > "$RFS/sbin/init" <<'INIT'
|
|
#!/bin/sh
|
|
# init de la imagen live de mirada. Arranca seatd + el compositor en modo greeter, y — lo importante para
|
|
# probar en una GPU AJENA — vuelca TODA la telemetría a la partición FAT32 del propio pendrive, para
|
|
# traerlo de vuelta con la información. El rootfs es un initramfs (RAM): sin esto no sobrevive NADA.
|
|
export PATH=/usr/bin:/bin:/usr/sbin:/sbin
|
|
/bin/busybox mount -t proc proc /proc 2>/dev/null || true
|
|
/bin/busybox mount -t sysfs sys /sys 2>/dev/null || true
|
|
/bin/busybox mount -t devtmpfs dev /dev 2>/dev/null || true
|
|
/bin/busybox mount -t tmpfs tmpfs /run 2>/dev/null || true
|
|
/bin/busybox mkdir -p /run/user/0 /dev/pts /dev/shm /run/seatd
|
|
/bin/busybox mount -t devpts devpts /dev/pts 2>/dev/null || true
|
|
/bin/busybox chmod 0700 /run/user/0
|
|
|
|
# ---------------------------------------------------------------- telemetría persistente al pendrive
|
|
# La partición la crea metal-usb-sdboot.sh (DATA_MB/DATA_LABEL). Se monta con -o sync: cada escritura va
|
|
# al medio, así un cuelgue duro de la GPU o un corte de luz no se lleva los logs.
|
|
LOG=/telemetry
|
|
TELOK=0
|
|
/bin/busybox mkdir -p $LOG
|
|
for try in 1 2 3 4 5 6 7 8 9 10; do
|
|
DEV=$(/bin/busybox findfs LABEL=MIRADALOG 2>/dev/null)
|
|
[ -n "$DEV" ] && break
|
|
/bin/busybox sleep 1 # el USB puede tardar en enumerar
|
|
done
|
|
if [ -n "$DEV" ] && /bin/busybox mount -t vfat -o rw,sync "$DEV" $LOG 2>/dev/null; then
|
|
TELOK=1
|
|
else
|
|
echo " !! NO pude montar la partición de telemetría (LABEL=MIRADALOG) — los logs quedan sólo en RAM"
|
|
LOG=/run
|
|
fi
|
|
|
|
# Cada arranque en su propia carpeta: run-0001, run-0002… (sin RTC confiable, se numera)
|
|
N=1
|
|
while [ -d "$LOG/run-$(printf %04d $N)" ]; do N=$((N+1)); done
|
|
RUN="$LOG/run-$(printf %04d $N)"
|
|
/bin/busybox mkdir -p "$RUN"
|
|
echo " ## telemetría → $RUN (persistente=$TELOK)"
|
|
# La bitácora interna del compositor (dlog → eventos.log + reportes de panic) también al pendrive:
|
|
# sin esto caía en ~/.local/state (RAM) y un viaje sin datos es un viaje perdido.
|
|
export MIRADA_DEBUG_DIR="$RUN"
|
|
|
|
snap() { # snap <fichero> <titulo> <comando…>
|
|
local f="$RUN/$1"; shift; local t="$1"; shift
|
|
{ echo "===== $t ====="; "$@" 2>&1; echo; } >> "$f"
|
|
/bin/busybox sync
|
|
}
|
|
|
|
# PCI desde sysfs: este busybox NO trae el applet `lspci`. Con vendor/device/class/driver alcanza para
|
|
# saber QUÉ GPU hay y, sobre todo, QUÉ DRIVER la bindeó (nouveau vs nada) — que es el dato del viaje.
|
|
# vendor 0x10de = NVIDIA · class 0x0300xx = VGA · 0x0302xx = 3D controller
|
|
pci_dump() {
|
|
for d in /sys/bus/pci/devices/*/; do
|
|
[ -r "$d/class" ] || continue
|
|
drv=$(/bin/busybox readlink "$d/driver" 2>/dev/null | /bin/busybox sed 's|.*/||')
|
|
echo "$(/bin/busybox basename $d) class=$(/bin/busybox cat $d/class) vendor=$(/bin/busybox cat $d/vendor) device=$(/bin/busybox cat $d/device) driver=${drv:-NINGUNO}"
|
|
done
|
|
}
|
|
gpu_line() {
|
|
for d in /sys/bus/pci/devices/*/; do
|
|
[ -r "$d/class" ] || continue
|
|
case "$(/bin/busybox cat $d/class)" in
|
|
0x0300*|0x0302*)
|
|
drv=$(/bin/busybox readlink "$d/driver" 2>/dev/null | /bin/busybox sed 's|.*/||')
|
|
echo "$(/bin/busybox basename $d) vendor=$(/bin/busybox cat $d/vendor) device=$(/bin/busybox cat $d/device) driver=${drv:-NINGUNO}" ;;
|
|
esac
|
|
done
|
|
}
|
|
|
|
# --- hardware / kernel: qué GPU hay, si nouveau bindeó, si cargó el firmware
|
|
snap 01-hardware.txt "uname" /bin/busybox uname -a
|
|
snap 01-hardware.txt "cmdline" /bin/busybox cat /proc/cmdline
|
|
snap 01-hardware.txt "cpu" /bin/busybox head -20 /proc/cpuinfo
|
|
snap 01-hardware.txt "memoria" /bin/busybox free -m
|
|
snap 01-hardware.txt "PCI (sysfs; vendor 0x10de=NVIDIA)" pci_dump
|
|
snap 01-hardware.txt "modulos" /bin/busybox cat /proc/modules
|
|
snap 01-hardware.txt "DRM /dev/dri" /bin/busybox ls -la /dev/dri
|
|
snap 01-hardware.txt "DRM /sys" /bin/busybox find /sys/class/drm -maxdepth 1
|
|
snap 01-hardware.txt "nouveau sysfs" /bin/busybox find /sys/module/nouveau -maxdepth 2
|
|
snap 01-hardware.txt "input" /bin/busybox cat /proc/bus/input/devices
|
|
snap 01-hardware.txt "firmware nvidia" /bin/busybox find /lib/firmware/nvidia -type f
|
|
for c in /sys/class/drm/card*/status /sys/class/drm/card*/modes /sys/class/drm/card*/enabled; do
|
|
[ -r "$c" ] && snap 02-pantallas.txt "$c" /bin/busybox cat "$c"
|
|
done
|
|
|
|
# dmesg TEMPRANO: acá se ve si nouveau bindeó y si el firmware gp106 cargó (o falló).
|
|
snap 03-dmesg-early.txt "dmesg (antes de mirada)" /bin/busybox dmesg
|
|
|
|
export XDG_RUNTIME_DIR=/run/user/0
|
|
export LIBGL_DRIVERS_PATH=/usr/lib/dri
|
|
export LIBSEAT_BACKEND=seatd
|
|
export XDG_SEAT=seat0
|
|
export XDG_SESSION_TYPE=wayland
|
|
export MIRADA_GREETER_BIN=/usr/bin/mirada-greeter
|
|
export XKB_DEFAULT_LAYOUT=us
|
|
export XKB_CONFIG_ROOT=/usr/share/X11/xkb
|
|
|
|
# Telemetría MÁXIMA del stack gráfico: por qué wgpu eligió (o no) el backend, y si hay float16.
|
|
export RUST_LOG="${RUST_LOG:-info,wgpu_core=debug,wgpu_hal=debug,mirada=debug,smithay=info}"
|
|
export RUST_BACKTRACE=full
|
|
export EGL_LOG_LEVEL=debug
|
|
export MESA_DEBUG=1
|
|
export LIBGL_DEBUG=verbose
|
|
|
|
# GPU: por defecto se INTENTA hardware (nouveau, si el firmware deja hacer modeset) y, si no, mesa cae a
|
|
# swrast/llvmpipe sobre simpledrm. Con `mirada.sw` en la cmdline se FUERZA software (necesario en la VM
|
|
# virtio-sin-virgl de validación). El compositor (smithay/GlesRenderer) corre en ambos; el greeter
|
|
# (wgpu/Vello) NECESITA shaders float16 (SHADER_FLOAT16_IN_FLOAT32) que llvmpipe/lavapipe NO dan ⇒ su
|
|
# login sólo pinta con GPU real (nouveau). Ver HANDOFF/README.
|
|
if grep -qw 'mirada.sw' /proc/cmdline 2>/dev/null; then
|
|
echo " ## modo SOFTWARE forzado (mirada.sw): compositor sí; greeter no (sin float16)"
|
|
MODO="software (mirada.sw)"
|
|
export LIBGL_ALWAYS_SOFTWARE=1
|
|
export GALLIUM_DRIVER=llvmpipe
|
|
export VK_ICD_FILENAMES=/usr/share/vulkan/icd.d/lvp_icd.x86_64.json
|
|
export VK_DRIVER_FILES=/usr/share/vulkan/icd.d/lvp_icd.x86_64.json
|
|
else
|
|
# HARDWARE (nouveau). En Pascal (GTX 10xx / GP10x) NVK NO existe (sólo Turing+) ⇒ el greeter debe ir
|
|
# por el backend GL de wgpu sobre gallium-nouveau (que sí da unpackHalf2x16 = float16). Forzamos GL y
|
|
# tapamos lavapipe: si dejáramos Vulkan, wgpu caería a lavapipe (software, sin float16) y fallaría.
|
|
echo " ## modo HARDWARE (nouveau GL): greeter por gallium-nouveau"
|
|
MODO="hardware (nouveau GL)"
|
|
export WGPU_BACKEND=gl
|
|
export VK_ICD_FILENAMES=/dev/null
|
|
fi
|
|
|
|
{ echo "modo : $MODO"; echo "cmdline : $(/bin/busybox cat /proc/cmdline)"; echo "DRM : $(/bin/busybox ls /dev/dri 2>/dev/null | tr '\n' ' ')";
|
|
echo "GPU (PCI) : $(gpu_line)";
|
|
echo "persistente: $TELOK"; echo "RUST_LOG : $RUST_LOG"; } > "$RUN/00-resumen.txt"
|
|
/bin/busybox sync
|
|
|
|
echo ""
|
|
echo " ## hammer · mirada live"
|
|
echo " ## DRM: $(ls /dev/dri 2>/dev/null | tr '\n' ' ')"
|
|
echo " ## telemetría: $RUN (persistente=$TELOK)"
|
|
echo ""
|
|
|
|
# seatd en background (gestiona el DRM master y la sesión sobre la VT).
|
|
/usr/bin/seatd -g video > "$RUN/04-seatd.log" 2>&1 &
|
|
/bin/busybox sleep 1
|
|
|
|
# El compositor: su salida va A LA VEZ a la pantalla y al pendrive (tee), para verlo y llevárselo.
|
|
echo "== lanzando mirada-compositor --drm --greeter =="
|
|
/usr/bin/mirada-compositor --drm --greeter 2>&1 | /bin/busybox tee "$RUN/05-mirada.log"
|
|
RC=$?
|
|
|
|
# --- post-mortem: lo que pasó DESPUÉS de correr mirada (cuelgues de GPU, oops, reset de nouveau)
|
|
snap 06-dmesg-final.txt "dmesg (después de mirada)" /bin/busybox dmesg
|
|
snap 06-dmesg-final.txt "rc del compositor" echo "exit=$RC"
|
|
snap 07-estado-final.txt "procesos" /bin/busybox ps
|
|
snap 07-estado-final.txt "memoria" /bin/busybox free -m
|
|
snap 07-estado-final.txt "DRM final" /bin/busybox ls -la /dev/dri
|
|
/bin/busybox sync
|
|
|
|
echo ""
|
|
echo "== mirada terminó (exit=$RC) — telemetría VOLCADA en $RUN =="
|
|
[ "$TELOK" = "1" ] && {
|
|
echo " Ficheros en el pendrive (partición MIRADALOG):"
|
|
/bin/busybox ls -la "$RUN"
|
|
echo ""
|
|
echo " >> Podés apagar y traer el pendrive: los logs ya están sincronizados al medio."
|
|
echo " >> Si querés reintentar antes de apagar, corré: relanzar"
|
|
} || echo " !! sin partición de telemetría: los logs están en RAM y se pierden al apagar"
|
|
echo ""
|
|
|
|
# `relanzar`: reintentar el compositor sin reiniciar; cada intento crea su propio run-NNNN.
|
|
cat > /usr/bin/relanzar <<'RL'
|
|
#!/bin/sh
|
|
echo "relanzando init (nuevo run-NNNN en el pendrive)…"
|
|
exec /sbin/init
|
|
RL
|
|
chmod +x /usr/bin/relanzar
|
|
|
|
echo "== shell de rescate (telemetría en $RUN; 'relanzar' para reintentar) =="
|
|
exec /bin/sh
|
|
INIT
|
|
chmod +x "$RFS/sbin/init"
|
|
# NO creamos /init: metal-usb-sdboot.sh escribe su propio /init (monta pseudofs y hace exec /sbin/init).
|
|
|
|
echo "==> rootfs listo: $RFS ($(du -sh "$RFS" | cut -f1))"
|
|
|
|
# 7) empaquetar imagen USB con el kernel linux-generic
|
|
if [ "$PACKAGE" = "1" ]; then
|
|
KGEN=$(ls -dt "$STORE"/*-linux-generic/boot/bzImage 2>/dev/null | head -1)
|
|
[ -n "$KGEN" ] || { echo "no encuentro el kernel linux-generic (build recipes/linux-generic.toml)" >&2; exit 1; }
|
|
echo "==> empaquetando USB (kernel linux-generic: $KGEN)"
|
|
# Cmdline por defecto = SOFTWARE (mirada.sw) + simpledrm (nouveau.modeset=0): garantiza que el
|
|
# COMPOSITOR arranca y se VE mirada en la pantalla de la NVIDIA en el primer boot, sin depender del
|
|
# driver ni del firmware. Para el greeter completo (login) hace falta GPU real: en el menú de
|
|
# systemd-boot, tecla 'e', quitá `mirada.sw nouveau.modeset=0` para que nouveau intente el hardware
|
|
# (requiere firmware GSP en /lib/firmware — ver FW_SRC).
|
|
# Default = HARDWARE nouveau (ya horneamos el firmware gp106): nouveau maneja la GTX 1060 y el greeter
|
|
# pinta por gallium-nouveau GL. Si nouveau diera problemas, en el menú (tecla 'e') agregá
|
|
# `mirada.sw nouveau.modeset=0` para caer a software (compositor sí, greeter no).
|
|
# DATA_MB: partición FAT32 de TELEMETRÍA. El rootfs de esta imagen es un initramfs = RAM pura, así que
|
|
# sin esta partición no sobrevive ni un log al apagado — y la GPU a probar está en otra máquina, lejos.
|
|
# El init la monta por LABEL=MIRADALOG con -o sync y vuelca ahí todo (ver /sbin/init).
|
|
# FAT32 ⇒ el pendrive se lee después desde cualquier SO, sin herramientas.
|
|
# `gpt` (force_gpt): la imagen dd-eada deja el GPT de respaldo en el MEDIO del disco (fin de la
|
|
# imagen, no del pendrive) y hay firmwares UEFI que lo "reparan" en el POST — reescriben el header
|
|
# primario apuntando las entradas a otro LBA sin copiarlas ⇒ primario INVÁLIDO. Linux, sin `gpt`,
|
|
# NO cae al respaldo con primario roto (block/partitions/efi.c) ⇒ cero particiones ⇒ findfs no ve
|
|
# MIRADALOG y la telemetría muere en RAM (pasó en el tester NVIDIA, 2026-07-16). Con `gpt` el kernel
|
|
# usa el respaldo y la telemetría sobrevive incluso con el primario mutilado.
|
|
ROOTFS="$RFS" KERNEL="$KGEN" IMG="work/hammer-mirada-usb.img" \
|
|
DATA_MB="${DATA_MB:-512}" DATA_LABEL="MIRADALOG" \
|
|
OPTIONS="${CMDLINE:-console=tty0 loglevel=4 gpt}" \
|
|
scripts/metal-usb-sdboot.sh
|
|
echo ""
|
|
echo "✓ imagen: work/hammer-mirada-usb.img"
|
|
echo " Al volver, leé la telemetría montando la partición MIRADALOG (FAT32) — carpetas run-NNNN/."
|
|
fi
|