TELEMETRÍA (el pedido): el rootfs de la imagen es un initramfs = RAM pura y los logs iban a /run (tmpfs) ⇒ al apagar la máquina ajena no sobrevivía NADA. Ahora la imagen lleva 2da partición FAT32 MIRADALOG (512M), montada por findfs+LABEL con -o sync (un cuelgue de GPU o corte de luz no se lleva los logs). Cada arranque vuelca run-NNNN/ con: resumen (modo/GPU/driver), hardware (PCI vía sysfs, módulos, DRM, input, firmware), pantallas (status/modes por conector), dmesg ANTES y DESPUÉS de mirada, seatd, y el log del compositor+greeter con RUST_LOG=wgpu_core=debug + EGL_LOG_LEVEL=debug + LIBGL_DEBUG=verbose (para ver por qué wgpu eligió el backend y si hay float16). Shell de rescate + . FAT32 a propósito: el pendrive se lee después desde cualquier SO. metal-usb-sdboot.sh gana DATA_MB/DATA_LABEL genéricos (partición de datos opcional en la GPT). GOTCHAs verificados antes de confiar: el kernel linux-generic SÍ trae VFAT_FS=y + NLS + USB_STORAGE=y (sin eso no montaba); el busybox de Alpine NO trae el applet 00:00.0 Host bridge: Intel Corporation Tiger Lake-UP3/H35 4 cores Host Bridge/DRAM Registers (rev 01) 00:02.0 VGA compatible controller: Intel Corporation TigerLake-LP GT2 [Iris Xe Graphics] (rev 01) 00:04.0 Signal processing controller: Intel Corporation TigerLake-LP Dynamic Tuning Processor Participant (rev 01) 00:07.0 PCI bridge: Intel Corporation Tiger Lake-LP Thunderbolt 4 PCI Express Root Port #0 (rev 01) 00:08.0 System peripheral: Intel Corporation GNA Scoring Accelerator module (rev 01) 00:0a.0 Signal processing controller: Intel Corporation Tigerlake Telemetry Aggregator Driver (rev 01) 00:0d.0 USB controller: Intel Corporation Tiger Lake-LP Thunderbolt 4 USB Controller (rev 01) 00:0d.2 USB controller: Intel Corporation Tiger Lake-LP Thunderbolt 4 NHI #0 (rev 01) 00:12.0 Serial controller: Intel Corporation 500 Series Chipset Family On-Package Integrated Sensor Hub (rev 20) 00:14.0 USB controller: Intel Corporation 500 Series Chipset Family On-Package USB 3.2 Gen 2x1 (10 Gbs) xHCI Host Controller (rev 20) 00:14.2 RAM memory: Intel Corporation 500 Series Chipset Family On-Package Shared SRAM (rev 20) 00:14.3 Network controller: Intel Corporation Wi-Fi 6 AX201 (rev 20) 00:15.0 Serial bus controller: Intel Corporation 500 Series Chipset Family On-Package I2C Controller #0 (rev 20) 00:15.1 Serial bus controller: Intel Corporation 500 Series Chipset Family On-Package I2C Controller #1 (rev 20) 00:16.0 Communication controller: Intel Corporation 500 Series Chipset Family On-Package CSME HECI #1 (rev 20) 00:1c.0 PCI bridge: Intel Corporation 500 Series Chipset Family On-Package PCI Express Root Port #5 (rev 20) 00:1d.0 PCI bridge: Intel Corporation 500 Series Chipset Family On-Package PCI Express Root Port #9 (rev 20) 00:1f.0 ISA bridge: Intel Corporation 500 Series Chipset Family On-Package eSPI Controller (rev 20) 00:1f.3 Multimedia audio controller: Intel Corporation 500 Series Chipset Family On-Package High Definition Audio (HD Audio) (rev 20) 00:1f.4 SMBus: Intel Corporation 500 Series Chipset Family On-Package System Management Bus (SMBus) (rev 20) 00:1f.5 Serial bus controller: Intel Corporation 500 Series Chipset Family On-Package SPI (flash) Controller (rev 20) 39:00.0 Non-Volatile memory controller: Kingston Technology Company, Inc. NV2 NVMe SSD [SM2267XT] (DRAM-less) (rev 03) 3a:00.0 Non-Volatile memory controller: ADATA Technology Co., Ltd. IM2P33F3 NVMe SSD (DRAM-less) (rev 03) (sí findfs/blkid) ⇒ el dump de PCI lee /sys/bus/pci/devices/*/ directo; sintaxis del init validada con busybox ash (no bash). BUMP mirada: el pin era 9967b02c (18-jun) — 439 commits viejo. Ahora 9a17fefc, que incluye el fix de portabilidad a musl que hice en tawasuyu (ioctl: glibc usa c_ulong, musl c_int ⇒ las constantes DRM casteaban mal y mirada-compositor NO compilaba para musl). mirada-compositor ya selló (87ced528); greeter/ctl en curso. + scripts/kde/{metal-desktop-image,plasma-start-metal}.sh del hilo KDE (imagen de escritorio en metal). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
400 lines
21 KiB
Bash
400 lines
21 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 hammer 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="${HAMMER:-target/release/hammer}"
|
|
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.
|
|
PKGS="mesa-swrast wayland libdrm seatd libinput libudev-zero libxkbcommon pixman linux-pam mtdev libevdev mirada-compositor mirada-greeter mirada-ctl"
|
|
|
|
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 hammer: 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
|
|
|
|
# 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)"
|
|
|
|
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.
|
|
ROOTFS="$RFS" KERNEL="$KGEN" IMG="work/hammer-mirada-usb.img" \
|
|
DATA_MB="${DATA_MB:-512}" DATA_LABEL="MIRADALOG" \
|
|
OPTIONS="${CMDLINE:-console=tty0 loglevel=4}" \
|
|
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
|