# 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"]