`firmware-tigerlake` cortaba con «falta regulatory.db», y no era un fallo suyo: upstream sacó ese fichero del tarball de linux-firmware y hoy sólo se publica en su propio proyecto de kernel.org. Comprobado sobre el artefacto sellado de linux-firmware 20260910: `find -name "regulatory*"` no devuelve nada. Lo que pasa sin ella no es «no hay WiFi», que sería fácil de notar: cfg80211 arranca, la tarjeta asocia, y se queda en el dominio `world` —pierde canales de 5 y 6 GHz y emite a la potencia mínima—. Un WiFi que funciona y va mal. La receta NO compila nada: el `make` del proyecto regenera la db y la firma con otra clave, y el kernel valida contra la que lleva compilada, así que regenerarla la rompería. Copia `regulatory.db` y su `.p7s` tal cual, y corta si la firma falta —sin firma, cfg80211 ignora la base y volvemos al dominio world, que es justo lo que veníamos a arreglar—. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
130 lines
7.5 KiB
TOML
130 lines
7.5 KiB
TOML
# firmware-tigerlake — los blobs que pide EXACTAMENTE la laptop del usuario, y nada más.
|
|
#
|
|
# ══ QUÉ MÁQUINA ES ═════════════════════════════════════════════════════════════════════════════
|
|
# Medido el 2026-09-16 sobre el metal real (`lspci -nn` + `lsmod`):
|
|
#
|
|
# 00:02.0 Intel TigerLake-LP GT2 [Iris Xe Graphics] [8086:9a49] ⇒ i915 / xe
|
|
# 00:14.3 Intel Wi-Fi 6 AX201 [8086:a0f0] ⇒ iwlwifi
|
|
# 00:1f.3 Intel 500 Series On-Package HD Audio [8086:a0c8] ⇒ snd_sof_pci_intel_tgl
|
|
#
|
|
# Es la misma máquina para la que ya se escribió `scripts/metal-firmware.sh`, que nombra estas tres
|
|
# familias y dice por qué: «son las tres familias de blobs que el metal necesita y ninguna se
|
|
# construye desde fuente». Esta receta es ese script convertido en artefacto sellado, con el
|
|
# firmware viniendo de `linux-firmware` pineado en vez de `/lib/firmware` del host.
|
|
#
|
|
# ══ POR QUÉ DERIVADA Y NO UN SEGUNDO FETCH ═════════════════════════════════════════════════════
|
|
# El árbol completo son ~2 GB extraídos. Esta máquina usa unos 25 MB de eso. Derivar de
|
|
# `linux-firmware` cuesta segundos y no mueve su hash, igual que `atuq` sobre `firefox` (SDD 26).
|
|
# Otro metal = otra receta derivada de dos líneas, no otro tarball de 648 MB.
|
|
#
|
|
# ══ SIN COMPRIMIR, A PROPÓSITO ═════════════════════════════════════════════════════════════════
|
|
# Los blobs se instalan planos (`.ucode`, `.bin`, `.ri`), no `.zst`. El kernel `linux-metal` **no
|
|
# habilita `FW_LOADER_COMPRESS`**, así que un firmware comprimido no se carga y el fallo aparece
|
|
# como «no WiFi» sin una línea que lo explique. Es la razón que ya está escrita en
|
|
# `metal-firmware.sh` y se repite acá porque es justo el tipo de cosa que se pierde al refactorizar.
|
|
#
|
|
# ⚠ **PUNTO DE PARTIDA, NO SELLADA.** Escrita desde el laptop, que no tiene lab ni store. Las
|
|
# aserciones de abajo están puestas para que el PRIMER BUILD falle ruidoso en vez de producir un
|
|
# artefacto flaco: un /lib/firmware a medias no falla al construir, falla meses después en el metal
|
|
# como «no hay WiFi» y nadie lo asocia con esta receta.
|
|
name = "firmware-tigerlake"
|
|
version = "20260910" # sigue a linux-firmware: no tiene versión propia
|
|
license = "LicenseRef-linux-firmware-various"
|
|
|
|
[source]
|
|
# No tiene fuente propia: todo su contenido sale de la dep. Se apunta al árbol vacío del repo por
|
|
# la misma razón que `atuq` usa `source.dir` — la identidad del artefacto son sus fases + su dep,
|
|
# y el `ArtifactHash` ya las incluye.
|
|
dir = "firmware-tigerlake"
|
|
|
|
[build]
|
|
compiler = "zig-cc"
|
|
target = "x86_64-linux-musl"
|
|
link = "static"
|
|
strip_debug = false
|
|
flags = []
|
|
|
|
[build.phases]
|
|
configure = "echo 'firmware-tigerlake: nada que configurar'"
|
|
compile = "echo 'firmware-tigerlake: nada que compilar — son blobs de la dep'"
|
|
install = '''
|
|
set -e
|
|
SRC=/lib/firmware
|
|
DST=/out/lib/firmware
|
|
|
|
# ── LAS ASERCIONES VAN PRIMERO (CLAUDE.md §3) ────────────────────────────────────────────────
|
|
# Un derivado que no encuentra su base produciría un /lib/firmware con cuatro ficheros, `Store::has`
|
|
# lo daría por presente, y el fallo saldría el día del arranque en metal como «no hay WiFi».
|
|
[ -d "$SRC" ] || { echo "firmware-tigerlake: no está el árbol de linux-firmware en $SRC" >&2; exit 1; }
|
|
[ -f "$SRC/WHENCE" ] || { echo "firmware-tigerlake: falta WHENCE — la dep no se materializó entera" >&2; exit 1; }
|
|
|
|
mkdir -p "$DST/intel/iwlwifi" "$DST/i915" "$DST/intel/sof" "$DST/intel/sof-tplg"
|
|
|
|
# ── 1. WiFi: Intel AX201 ─────────────────────────────────────────────────────────────────────
|
|
# El driver elige la API MÁS ALTA que soporta, así que se copian TODAS las revisiones de las dos
|
|
# familias y no sólo la última: qué número pide depende del kernel, no de nosotros.
|
|
# Upstream movió los .ucode a intel/iwlwifi/ y dejó symlinks en la raíz; se cubren los dos sitios.
|
|
wifi=0
|
|
for pat in "iwlwifi-QuZ-a0-hr-b0-*.ucode" "iwlwifi-cc-a0-*.ucode"; do
|
|
for d in "$SRC/intel/iwlwifi" "$SRC"; do
|
|
for f in "$d"/$pat; do
|
|
[ -f "$f" ] || continue
|
|
cp -L "$f" "$DST/intel/iwlwifi/" && wifi=$((wifi+1))
|
|
done
|
|
done
|
|
done
|
|
# El driver busca en /lib/firmware antes que en intel/iwlwifi ⇒ se dejan los dos caminos.
|
|
for f in "$DST"/intel/iwlwifi/*.ucode; do
|
|
[ -f "$f" ] && cp -L "$f" "$DST/" || true
|
|
done
|
|
[ "$wifi" -gt 0 ] || { echo "firmware-tigerlake: 0 blobs de iwlwifi — el AX201 no va a asociar" >&2; exit 1; }
|
|
|
|
# regulatory.db: cfg80211 lo verifica contra la clave built-in del kernel. Sin él el WiFi queda
|
|
# limitado al dominio world y en la práctica no ve la mitad de los canales.
|
|
for f in regulatory.db regulatory.db.p7s; do
|
|
[ -f "$SRC/$f" ] && cp -L "$SRC/$f" "$DST/"
|
|
done
|
|
[ -f "$DST/regulatory.db" ] || { echo "firmware-tigerlake: falta regulatory.db" >&2; exit 1; }
|
|
|
|
# ── 2. Gráficos: i915 / xe en TigerLake ──────────────────────────────────────────────────────
|
|
# DMC = display microcontroller (sin él no hay ahorro de energía del display ni, en algunos
|
|
# kernels, modeset fiable). GuC/HuC = submission y decodificación por hardware.
|
|
gfx=0
|
|
for f in "$SRC"/i915/tgl_*.bin; do
|
|
[ -f "$f" ] || continue
|
|
cp -L "$f" "$DST/i915/" && gfx=$((gfx+1))
|
|
done
|
|
[ "$gfx" -gt 0 ] || { echo "firmware-tigerlake: 0 blobs de i915 tgl — el display va a ir sin DMC" >&2; exit 1; }
|
|
|
|
# ── 3. Audio: SOF en el DSP de TigerLake ─────────────────────────────────────────────────────
|
|
# El SOF **no viene en linux-firmware** — se midió sobre el tarball (0 coincidencias con
|
|
# `intel/sof`) y por eso existe `recipes/sof-firmware.toml`, que es dep de esta receta. Acá sólo se
|
|
# recoge lo que aquélla ya dejó en su sitio: es la misma jugada que con la dep de linux-firmware.
|
|
snd=0
|
|
if [ -d "$SRC/intel/sof" ]; then
|
|
mkdir -p "$DST/intel/sof/intel-signed"
|
|
for f in "$SRC"/intel/sof/intel-signed/sof-tgl*.ri; do
|
|
[ -f "$f" ] || continue
|
|
cp "$f" "$DST/intel/sof/intel-signed/"
|
|
ln -sf "intel-signed/$(basename "$f")" "$DST/intel/sof/$(basename "$f")"
|
|
snd=$((snd+1))
|
|
done
|
|
fi
|
|
if [ -d "$SRC/intel/sof-tplg" ]; then
|
|
for f in "$SRC"/intel/sof-tplg/sof-hda-generic*.tplg; do
|
|
[ -f "$f" ] && cp -L "$f" "$DST/intel/sof-tplg/" && snd=$((snd+1))
|
|
done
|
|
fi
|
|
[ "$snd" -gt 0 ] || { echo "firmware-tigerlake: 0 blobs de SOF — ¿se materializó la dep sof-firmware?" >&2; exit 1; }
|
|
|
|
n=$(find "$DST" -type f | wc -l)
|
|
echo "firmware-tigerlake: $n ficheros (wifi=$wifi i915=$gfx sof=$snd)"
|
|
'''
|
|
|
|
[deps]
|
|
# `wireless-regdb` entró el 2026-09-17: `regulatory.db` **ya no viene en linux-firmware** —upstream
|
|
# lo sacó, es un proyecto aparte de kernel.org— y esta receta cortaba con «falta regulatory.db».
|
|
# Como las deps se materializan en el mismo `/lib/firmware`, el bucle de copia lo encuentra sin
|
|
# tocar una línea del guion.
|
|
build = ["linux-firmware", "sof-firmware", "wireless-regdb", "busybox"]
|