firmware del metal: el TODO de soberanía cerrado — los blobs dejan de copiarse del host
`scripts/metal-firmware.sh` llevaba desde que se escribió con este pie:
TODO(soberanía): reemplazar FWSRC=host por un pin a un commit de linux-firmware
Eso significaba que una imagen de takana para el metal sólo se podía armar desde una
máquina que YA tuviera el firmware instalado por otra distro. Un instalador que sólo se
puede construir desde la distro a la que viene a reemplazar no es un instalador.
Cuatro recetas, y la partición entre ellas es la decisión:
· linux-firmware — tarball 20260910 pineado. 648 MB, ~2 GB extraídos. Es una BASE y no
entra en ningún perfil: nadie manda eso en una imagen de escritorio.
· firmware-tigerlake — DERIVADA, recorta ~25 MB: las tres familias que este metal pide.
Es la que viaja. Otro metal = otra derivada de dos líneas, no otro fetch de 648 MB.
Misma economía que atuq sobre firefox (SDD 26).
· sof-firmware — porque el SOF NO viene en linux-firmware. Medido, no supuesto:
entradas del tarball ... 5323
intel/sof .............. 0 ✗
i915/tgl ............... 15 ✓
iwlwifi ................ 201 ✓
· intel-ucode — tampoco viene: trae amd-ucode pero el de Intel lo publica Intel.
Y una contraintuitiva que queda escrita para no re-tropezarla: TigerLake va por IPC3, no
por IPC4. Lo esperable era tomar la serie más alta de sof-bin (v2.14.x); medido, esa serie
no contiene NINGÚN fichero tgl. El firmware de TGL sólo existe en la rama IPC3, y el más
nuevo que lo trae es v2.2.x/sof-v2.2/sof-tgl.ri.
El sha256 de linux-firmware se contrastó contra el sha256sums.asc que kernel.org publica
firmado — no contra el fichero que bajamos, que sería comprobar que un fichero es igual a
sí mismo.
⚠ NINGUNA ESTÁ SELLADA: escritas desde el laptop, que no tiene lab ni store. Las aserciones
de cada `install` están puestas para que el primer build falle ruidoso en vez de producir
un /lib/firmware a medias — que no falla al construir y falla meses después en el metal
como «no hay WiFi», sin una línea que lo asocie con esto (CLAUDE.md §3).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,125 @@
|
||||
# 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]
|
||||
build = ["linux-firmware", "sof-firmware", "busybox"]
|
||||
@@ -0,0 +1,4 @@
|
||||
Esta receta no tiene fuente propia: su contenido sale enteramente de sus deps
|
||||
(linux-firmware + sof-firmware). El directorio existe porque `source.dir` exige un
|
||||
árbol que hashear — el mismo patrón que usa `recipes/atuq/`. Ver el encabezado de
|
||||
../firmware-tigerlake.toml.
|
||||
@@ -0,0 +1,75 @@
|
||||
# intel-ucode 20260812 — el microcódigo de la CPU. Va en el arranque, no en el userland.
|
||||
#
|
||||
# ══ POR QUÉ NO VIENE EN linux-firmware ═════════════════════════════════════════════════════════
|
||||
# El tarball de kernel.org trae `amd-ucode` pero **no el de Intel**: Intel lo publica por su cuenta
|
||||
# en `intel/Intel-Linux-Processor-Microcode-Data-Files`, con su propia licencia. Medido sobre
|
||||
# `linux-firmware-20260910.tar.xz` el 2026-09-16.
|
||||
#
|
||||
# ══ QUÉ CPU ═══════════════════════════════════════════════════════════════════════════════════
|
||||
# La laptop del usuario, leída de `/proc/cpuinfo`:
|
||||
#
|
||||
# 11th Gen Intel Core i7-11370H family 6 · model 140 (0x8c) · stepping 1
|
||||
# ⇒ le toca `intel-ucode/06-8c-01` (microcódigo corriendo hoy: 0xbe)
|
||||
#
|
||||
# La receta instala el árbol ENTERO igual, no sólo ese fichero: el cargador elige por signature en
|
||||
# boot, y recortarlo ataría el artefacto a esta máquina exacta — que es justo lo que
|
||||
# `firmware-tigerlake` hace a propósito y esto no debe hacer. Son 17 MB comprimidos.
|
||||
#
|
||||
# ══ LOS DOS CAMINOS DE CARGA, Y POR QUÉ HACEN FALTA LOS DOS ════════════════════════════════════
|
||||
# · **Tardía** (`/lib/firmware/intel-ucode/<sig>`): el kernel la aplica con el sistema ya arriba.
|
||||
# Sirve, pero llega después de que las mitigaciones de CPU se hayan decidido.
|
||||
# · **Temprana** (`kernel/x86/microcode/GenuineIntel.bin` dentro de un cpio SIN comprimir, al
|
||||
# principio del initramfs): el kernel la lee antes de levantar los cores secundarios. Es la que
|
||||
# de verdad importa, y es la que hay que enganchar en el armado de la imagen.
|
||||
#
|
||||
# Esta receta deja los dos: el árbol plano y el `GenuineIntel.bin` ya concatenado, listo para que
|
||||
# el armador de la imagen lo prependa. **No arma el cpio** — eso es trabajo de la imagen, no del
|
||||
# artefacto, y meterlo acá obligaría a esta receta a saber cómo se arma el initramfs.
|
||||
#
|
||||
# ⚠ **PUNTO DE PARTIDA, NO SELLADA.** Escrita desde el laptop, sin lab ni store.
|
||||
name = "intel-ucode"
|
||||
version = "20260812"
|
||||
license = "LicenseRef-Intel-Software-License" # license/LICENSE en el árbol; NO es libre
|
||||
|
||||
[source]
|
||||
tarball = "https://github.com/intel/Intel-Linux-Processor-Microcode-Data-Files/archive/refs/tags/microcode-20260812.tar.gz"
|
||||
# sha256 del tarball bajado el 2026-09-16.
|
||||
sha256 = "7614616d7b2988c278060486f47de716ef44c19317928cb45ac9e288fafd5bd1"
|
||||
|
||||
[build]
|
||||
compiler = "zig-cc"
|
||||
target = "x86_64-linux-musl"
|
||||
link = "static"
|
||||
strip_debug = false
|
||||
flags = []
|
||||
|
||||
[build.phases]
|
||||
configure = "echo 'intel-ucode: nada que configurar'"
|
||||
compile = "echo 'intel-ucode: nada que compilar'"
|
||||
install = '''
|
||||
set -e
|
||||
[ -d intel-ucode ] || { echo "intel-ucode: no está el dir intel-ucode/ — ¿cambió el layout del release?" >&2; exit 1; }
|
||||
|
||||
mkdir -p /out/lib/firmware/intel-ucode
|
||||
cp intel-ucode/* /out/lib/firmware/intel-ucode/
|
||||
|
||||
# Aserción ruidosa: el árbol tiene ~130 signatures. Si llegan cuatro, algo se cortó.
|
||||
n=$(find /out/lib/firmware/intel-ucode -type f | wc -l)
|
||||
[ "$n" -gt 50 ] || { echo "intel-ucode: sólo $n signatures — el árbol llegó incompleto" >&2; exit 1; }
|
||||
|
||||
# La signature de la laptop del usuario. No se recorta el árbol por ella, pero SÍ se comprueba que
|
||||
# está: si un release futuro la dejara caer, el metal quedaría sin microcódigo en silencio.
|
||||
[ -f /out/lib/firmware/intel-ucode/06-8c-01 ] || {
|
||||
echo "intel-ucode: falta 06-8c-01 (TigerLake i7-11370H) — el metal del usuario se queda sin ucode" >&2; exit 1; }
|
||||
|
||||
# Blob para carga TEMPRANA: todas las signatures concatenadas, que es exactamente el formato que el
|
||||
# cargador del kernel espera en kernel/x86/microcode/GenuineIntel.bin.
|
||||
mkdir -p /out/usr/share/intel-ucode
|
||||
cat intel-ucode/* > /out/usr/share/intel-ucode/GenuineIntel.bin
|
||||
[ -s /out/usr/share/intel-ucode/GenuineIntel.bin ] || { echo "intel-ucode: GenuineIntel.bin salió vacío" >&2; exit 1; }
|
||||
|
||||
echo "intel-ucode: $n signatures + GenuineIntel.bin ($(wc -c < /out/usr/share/intel-ucode/GenuineIntel.bin) B)"
|
||||
'''
|
||||
|
||||
[deps]
|
||||
build = ["busybox"]
|
||||
@@ -0,0 +1,75 @@
|
||||
# linux-firmware 20260910 — los BLOBS del hardware. La receta que le faltaba al metal.
|
||||
#
|
||||
# ══ POR QUÉ ESTA RECETA ROMPE LA REGLA, Y POR QUÉ ESTÁ BIEN ════════════════════════════════════
|
||||
# takana compila todo desde fuente. Esto NO se compila desde fuente: es firmware binario que Intel,
|
||||
# Realtek y el resto no liberan. La soberanía de «reproducir, no confiar» **no aplica** acá, igual
|
||||
# que no aplica al microcódigo de la CPU: son DATOS FIJOS, no código que podamos auditar ni
|
||||
# rebuildear. Lo que sí podemos hacer —y hacemos— es **fijarlos por contenido**: un tarball con su
|
||||
# sha256, como cualquier fuente pineada (ADR 0006). El artefacto es reproducible aunque su
|
||||
# contenido sea opaco.
|
||||
#
|
||||
# ══ QUÉ TODO CIERRA ════════════════════════════════════════════════════════════════════════════
|
||||
# `scripts/metal-firmware.sh` lleva desde que se escribió con este comentario al pie:
|
||||
#
|
||||
# TODO(soberanía): reemplazar FWSRC=host por un pin a un commit de linux-firmware
|
||||
# (recipe fetch+extract).
|
||||
#
|
||||
# Eso es esta receta. Hasta hoy el firmware del metal se COPIABA DEL HOST (`/lib/firmware` de la
|
||||
# Artix del usuario), lo que significa que una imagen de takana sólo se podía armar desde una
|
||||
# máquina que ya tuviera el firmware correcto instalado por otra distro. Un instalador que hay que
|
||||
# construir desde la distro que viene a reemplazar no es un instalador.
|
||||
#
|
||||
# ══ PESA 648 MB COMPRIMIDO, Y POR ESO NO VA EN NINGÚN PERFIL ═══════════════════════════════════
|
||||
# El árbol extraído son ~2 GB: firmware de todas las GPU, WiFi, bluetooth, DSP y controladoras que
|
||||
# Linux conoce. Meter eso en una imagen de escritorio sería absurdo. **Esta receta es una BASE, no
|
||||
# un miembro de perfil**: quien la consume es `firmware-tigerlake`, que extrae las cuatro familias
|
||||
# que una laptop concreta pide. Si mañana hay otro metal, es otra receta derivada de dos líneas —
|
||||
# no un segundo fetch de 648 MB.
|
||||
#
|
||||
# Por eso `perfiles` no la reclama nadie en `targets.toml`: entra por la dep de su derivada.
|
||||
name = "linux-firmware"
|
||||
version = "20260910"
|
||||
license = "LicenseRef-linux-firmware-various" # cada blob trae su propia licencia en WHENCE
|
||||
|
||||
[source]
|
||||
tarball = "https://cdn.kernel.org/pub/linux/kernel/firmware/linux-firmware-20260910.tar.xz"
|
||||
# sha256 bajado y calculado el 2026-09-16, y **contrastado contra el `sha256sums.asc` que kernel.org
|
||||
# publica firmado en el mismo directorio** — no sólo contra el fichero que bajamos, que sería
|
||||
# comprobar que un fichero es igual a sí mismo. Coinciden.
|
||||
sha256 = "f3937ca282ba256242e2b6dbe523df8a80007d29ffd61f56d270190865492ea8"
|
||||
|
||||
# ══ QUÉ TRAE Y QUÉ NO — MEDIDO SOBRE EL TARBALL, NO SUPUESTO ═══════════════════════════════════
|
||||
# entradas ........ 5323
|
||||
# i915/tgl ........ 15 ✓ (DMC, GuC, HuC de TigerLake)
|
||||
# iwlwifi ......... 201 ✓ (en `intel/iwlwifi/`, no en la raíz)
|
||||
# intel/sof ....... 0 ✗ ⇒ el audio va por `recipes/sof-firmware.toml`, aparte
|
||||
# amd-ucode ....... sí (pero el microcódigo de Intel NO: lo publica Intel por su cuenta)
|
||||
|
||||
[build]
|
||||
compiler = "zig-cc" # entra en el hash aunque no se compile nada; se deja el default del corpus
|
||||
target = "x86_64-linux-musl"
|
||||
link = "static"
|
||||
strip_debug = false # son blobs: no hay secciones de depuración que separar
|
||||
flags = []
|
||||
|
||||
[build.phases]
|
||||
configure = "echo 'linux-firmware: nada que configurar — son blobs'"
|
||||
compile = "echo 'linux-firmware: nada que compilar — son blobs'"
|
||||
# El `install` del propio árbol (`make install`) usa un script que depende de rdfind/symlink
|
||||
# rewriting. Se evita: copiar el árbol tal cual es más simple y no pierde los symlinks internos
|
||||
# (cp -a los preserva), que es exactamente lo que el kernel espera encontrar.
|
||||
install = '''
|
||||
set -e
|
||||
mkdir -p /out/lib/firmware
|
||||
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.
|
||||
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"
|
||||
'''
|
||||
|
||||
[deps]
|
||||
build = ["busybox"]
|
||||
@@ -0,0 +1,97 @@
|
||||
# sof-firmware 2025.12.2 — el DSP de audio de Intel. NO viene en linux-firmware, y eso se midió.
|
||||
#
|
||||
# ══ POR QUÉ ES UNA RECETA APARTE ═══════════════════════════════════════════════════════════════
|
||||
# Al escribir `firmware-tigerlake` se anotó como duda si `intel/sof*` venía dentro de
|
||||
# `linux-firmware`. Se midió sobre el tarball real (`linux-firmware-20260910.tar.xz`, 2026-09-16):
|
||||
#
|
||||
# entradas del tarball ......... 5323
|
||||
# coincidencias con intel/sof .. 0
|
||||
# i915/tgl ..................... 15 ✓
|
||||
# iwlwifi ...................... 201 ✓
|
||||
#
|
||||
# ⇒ **no viene.** Intel publica el SOF por su cuenta, en `thesofproject/sof-bin`. Sin esta receta
|
||||
# una imagen de takana en el metal del usuario arranca muda: `snd_sof_pci_intel_tgl` carga, pide
|
||||
# `intel/sof/sof-tgl.ri`, no lo encuentra y el DSP no levanta. Es un fallo que no se ve en QEMU,
|
||||
# donde el audio es virtio — por eso no apareció en ninguno de los tres escritorios ya cerrados.
|
||||
#
|
||||
# ══ TIGERLAKE VA POR IPC3, NO POR IPC4 — Y LA INTUICIÓN ES LA CONTRARIA ════════════════════════
|
||||
# IPC4 es el camino nuevo y el default en las plataformas recientes, así que lo esperable sería
|
||||
# tomar la serie más alta (`v2.14.x`). Medido sobre el tarball de sof-bin: **`sof-ipc4-v2.14.1` no
|
||||
# contiene NINGÚN fichero `tgl`**. El firmware de TigerLake sólo existe en la rama IPC3, y el más
|
||||
# nuevo que lo trae es `v2.2.x/sof-v2.2/sof-tgl.ri`. Las topologías van con él: `sof-tplg-v2.2`.
|
||||
#
|
||||
# tar -tzf sof-bin.tar.gz | grep "sof-ipc4-v2.14.1" | grep -i tgl ⇒ vacío
|
||||
# tar -tzf sof-bin.tar.gz | grep -E "/sof-v[0-9.]+/sof-tgl\.ri$" ⇒ v2.1.1, v2.2
|
||||
#
|
||||
# Si algún día se sube de serie, esto se re-mide: tomar «la más alta» es exactamente el error que
|
||||
# esta nota existe para evitar.
|
||||
#
|
||||
# ══ intel-signed VS community ══════════════════════════════════════════════════════════════════
|
||||
# El árbol trae las dos firmas del mismo binario. Se instala **intel-signed**, que es el que la
|
||||
# Artix del usuario tiene enlazado hoy (`sof-tgl.ri → intel-signed/sof-tgl.ri`) y el único que el
|
||||
# DSP acepta con secure boot del audio activo. `community` es para DSP desbloqueados.
|
||||
#
|
||||
# ⚠ **PUNTO DE PARTIDA, NO SELLADA.** Escrita desde el laptop, sin lab ni store. Primer build en el
|
||||
# worker.
|
||||
name = "sof-firmware"
|
||||
version = "2025.12.2"
|
||||
license = "BSD-3-Clause" # LICENCE.Intel en la raíz del árbol
|
||||
|
||||
[source]
|
||||
tarball = "https://github.com/thesofproject/sof-bin/archive/refs/tags/v2025.12.2.tar.gz"
|
||||
# sha256 del tarball bajado el 2026-09-16.
|
||||
sha256 = "a5fb05464273a2963a35950be72e094c0ed89318a44b3c62cb0c93393436ae3c"
|
||||
|
||||
[build]
|
||||
compiler = "zig-cc"
|
||||
target = "x86_64-linux-musl"
|
||||
link = "static"
|
||||
strip_debug = false # blobs firmados: tocarlos invalida la firma
|
||||
flags = []
|
||||
|
||||
[build.phases]
|
||||
configure = "echo 'sof-firmware: nada que configurar — son blobs firmados'"
|
||||
compile = "echo 'sof-firmware: nada que compilar — son blobs firmados'"
|
||||
# NO se usa el `install.sh` del árbol: hace rsync a `/lib/firmware` del sistema vivo y decide la
|
||||
# serie por variables de entorno. Acá la serie es una DECISIÓN de la receta y entra en el hash.
|
||||
install = '''
|
||||
set -e
|
||||
FW=v2.2.x/sof-v2.2
|
||||
TPLG=v2.2.x/sof-tplg-v2.2
|
||||
DST=/out/lib/firmware/intel
|
||||
|
||||
[ -d "$FW" ] || { echo "sof-firmware: no está $FW — ¿cambió el layout de sof-bin?" >&2; exit 1; }
|
||||
[ -d "$TPLG" ] || { echo "sof-firmware: no está $TPLG" >&2; exit 1; }
|
||||
|
||||
mkdir -p "$DST/sof/intel-signed" "$DST/sof-tplg"
|
||||
|
||||
# ── firmware del DSP ─────────────────────────────────────────────────────────────────────────
|
||||
# Sólo las variantes de TigerLake: `sof-tgl.ri` (LP, que es esta laptop) y `sof-tgl-h.ri` (H).
|
||||
# El árbol entero son ~80 MB de plataformas que este metal no tiene.
|
||||
n=0
|
||||
for v in sof-tgl.ri sof-tgl-h.ri; do
|
||||
if [ -f "$FW/intel-signed/$v" ]; then
|
||||
cp "$FW/intel-signed/$v" "$DST/sof/intel-signed/$v"
|
||||
# El driver pide `intel/sof/sof-tgl.ri` a secas; el symlink es el que usa la distro de origen.
|
||||
ln -sf "intel-signed/$v" "$DST/sof/$v"
|
||||
n=$((n+1))
|
||||
fi
|
||||
done
|
||||
[ "$n" -gt 0 ] || { echo "sof-firmware: 0 blobs de tgl en $FW/intel-signed" >&2; exit 1; }
|
||||
|
||||
# ── topologías ───────────────────────────────────────────────────────────────────────────────
|
||||
# `sof-hda-generic-*.tplg` es lo que monta el HD Audio on-package del 500 Series. Cuál de las
|
||||
# variantes (1ch/2ch/4ch, con o sin kwd) elige el driver depende del códec detectado en boot, así
|
||||
# que van todas las genéricas: son unos pocos KB cada una y elegir a mano sería adivinar.
|
||||
t=0
|
||||
for f in "$TPLG"/sof-hda-generic*.tplg; do
|
||||
[ -f "$f" ] || continue
|
||||
cp "$f" "$DST/sof-tplg/" && t=$((t+1))
|
||||
done
|
||||
[ "$t" -gt 0 ] || { echo "sof-firmware: 0 topologías hda-generic en $TPLG" >&2; exit 1; }
|
||||
|
||||
echo "sof-firmware: $n firmware + $t topologías (serie IPC3 v2.2, TigerLake)"
|
||||
'''
|
||||
|
||||
[deps]
|
||||
build = ["busybox"]
|
||||
Reference in New Issue
Block a user