From f7efbdb8061eaaacb680528a6135461d89ea0911 Mon Sep 17 00:00:00 2001 From: Sergio Date: Thu, 17 Sep 2026 21:25:41 +0000 Subject: [PATCH] =?UTF-8?q?linux-firmware:=20los=20~2400=20enlaces=20que?= =?UTF-8?q?=20el=20tarball=20NO=20trae,=20y=20una=20aserci=C3=B3n=20que=20?= =?UTF-8?q?envejec=C3=ADa=20mal?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Dos defectos medidos el 2026-09-17 al construirla por primera vez en la caja. 1) La receta decía «cp -a preserva los symlinks internos, que es lo que el kernel espera». La premisa es FALSA: `find -type l` sobre el árbol desempaquetado da 0. Los ~2400 enlaces los crea copy-firmware.sh al instalar, leyéndolos de WHENCE, y esta receta evita ese script porque pide rdfind. El resultado habría sido un artefacto de 1,9 G, sellado y reproducible, con iwlwifi MUDO: el driver pide `iwlwifi-QuZ-a0-hr-b0-77.ucode` en la raíz y el blob vive en intel/iwlwifi/. Justo el metal al que apunta firmware-tigerlake (TigerLake/AX201) se quedaba sin WiFi. Ahora se crean desde WHENCE, cuyo destino es relativo al directorio del enlace, y sólo si el destino existe. 2) La aserción de completitud era `> 5000 ficheros`, medida sobre una versión vieja. La 20260910 trae 4889 y el guardián la rechazaba POR COMPLETA. Un umbral escrito a mano envejece y miente en la dirección cara: frena lo bueno y hace dudar del tarball, que estaba pineado por sha256 y era el correcto. Ahora se le pregunta a WHENCE, que viaja dentro del tarball y declara cuántos blobs hay. Co-Authored-By: Claude Opus 5 (1M context) --- recipes/linux-firmware.toml | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/recipes/linux-firmware.toml b/recipes/linux-firmware.toml index fb05e54d..72a96f59 100644 --- a/recipes/linux-firmware.toml +++ b/recipes/linux-firmware.toml @@ -65,10 +65,40 @@ cp -a ./* /out/lib/firmware/ # WHENCE es el índice de licencias por blob. Se conserva: es la única trazabilidad legal que # tienen estos ficheros y `scripts/licencias-*.sh` lo va a querer leer. [ -f /out/lib/firmware/WHENCE ] || { echo "linux-firmware: falta WHENCE — el tarball no es el que se espera" >&2; exit 1; } -# Aserción ruidosa (CLAUDE.md §3): un árbol de firmware vacío pasaría por artefacto presente. + +# ── LOS ENLACES, QUE EL TARBALL NO TRAE (medido 2026-09-17) ───────────────────────────────────── +# Esta receta decía «cp -a preserva los symlinks internos, que es lo que el kernel espera». La +# premisa es FALSA: `find -type l` sobre el árbol desempaquetado da **0**. Los ~2400 enlaces los +# crea `copy-firmware.sh` AL INSTALAR, leyéndolos de WHENCE, y esta receta evita ese script (pide +# rdfind). Resultado: un artefacto de 1,9 G, sellado y reproducible, en el que **iwlwifi no carga** +# — el driver pide `iwlwifi-QuZ-a0-hr-b0-77.ucode` en la raíz y el blob vive en `intel/iwlwifi/`. +# Justo el metal al que apunta `firmware-tigerlake` (TigerLake/AX201) se queda sin WiFi. +# El destino de cada `Link:` es relativo AL DIRECTORIO DEL ENLACE, no a /lib/firmware. +sed -n 's/^Link:[[:space:]]*//p' /out/lib/firmware/WHENCE \ + | sed 's/[[:space:]]*->[[:space:]]*/\t/' > /tmp/whence-links.tsv +declarados=$(wc -l < /tmp/whence-links.tsv) +hechos=0 +while IFS="$(printf '\t')" read -r dst src; do + [ -n "$dst" ] && [ -n "$src" ] || continue + dir=$(dirname "/out/lib/firmware/$dst") + [ -e "$dir/$src" ] || continue # sólo si el destino existe de verdad + mkdir -p "$dir" + ln -sf "$src" "/out/lib/firmware/$dst" + hechos=$((hechos+1)) +done < /tmp/whence-links.tsv +echo "linux-firmware: $hechos/$declarados enlaces de WHENCE creados" +[ "$hechos" -ge $((declarados * 9 / 10)) ] || { echo "linux-firmware: sólo $hechos de $declarados enlaces — el árbol no casa con su WHENCE" >&2; exit 1; } + +# ── Aserción de completitud, CONTRA WHENCE y no contra un número mágico ───────────────────────── +# Antes decía `> 5000 ficheros`, medido sobre una versión vieja. La 20260910 trae 4889 y el guardián +# la rechazaba por completa: un umbral a mano envejece y miente en la dirección cara (frena lo bueno). +# WHENCE viaja DENTRO del tarball y dice cuántos blobs debería haber: se le pregunta a él. n=$(find /out/lib/firmware -type f | wc -l) -[ "$n" -gt 5000 ] || { echo "linux-firmware: sólo $n ficheros — el árbol llegó incompleto" >&2; exit 1; } -echo "linux-firmware: $n ficheros instalados" +decl=$(grep -c "^File:" /out/lib/firmware/WHENCE) +[ "$n" -ge "$decl" ] || { echo "linux-firmware: $n ficheros y WHENCE declara $decl — el árbol llegó incompleto" >&2; exit 1; } +echo "linux-firmware: $n ficheros instalados (WHENCE declara $decl)" +# El control que de verdad importa para el metal de esta casa: +[ -e /out/lib/firmware/i915 ] || { echo "linux-firmware: falta i915 — el gráfico de TigerLake no arrancaría" >&2; exit 1; } ''' [deps]