fix(arje): build-initrd compila musl-static por default
Sin musl, PID 1 panic con "error while loading shared libraries: libgcc_s.so.1" porque el initramfs no incluye libgcc/glibc/ld-linux. Solución estándar: target x86_64-unknown-linux-musl produce un ELF totalmente estático. Cambios en scripts/build-arje-initrd.sh: - ARJE_TARGET=x86_64-unknown-linux-musl por default (override con env). - Chequeo del target instalado antes de buildear; mensaje accionable con los comandos exactos (rustup target add..., apt install musl-tools, etc.) si falta. - Sanity check con `file`: aborta si ente-zero quedó dinámico. - Sanity check para busybox: aborta si el BUSYBOX_BIN apunta a un binario dinámico (la otra causa #1 de panic). - BIN_DIR ahora apunta a target/$TARGET/release/. Docs (docs/arje-boot.md): - §2a explica el porqué de musl. - §2b lista requisitos del host (rustup target, musl-tools, busybox-static). - §7 sección nueva de troubleshooting con el síntoma exacto del libgcc_s panic + 3 escenarios comunes más. - Checklist pre-deploy actualizado con el chequeo de "statically linked". Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
+126
-16
@@ -22,12 +22,12 @@ El initrd es un **CPIO + gzip** (formato `newc`, estándar Linux). Su raíz:
|
|||||||
|
|
||||||
```
|
```
|
||||||
/init wrapper sh, ejecuta /sbin/ente-zero
|
/init wrapper sh, ejecuta /sbin/ente-zero
|
||||||
/sbin/ente-zero PID 1
|
/sbin/ente-zero PID 1 (musl-static por default)
|
||||||
/usr/sbin/ente-echo
|
/usr/sbin/ente-echo
|
||||||
/usr/sbin/ente-policy-provider
|
/usr/sbin/ente-policy-provider
|
||||||
/usr/sbin/ente-*-compat 13 shims D-Bus (logind, hostnamed, …)
|
/usr/sbin/ente-*-compat 13 shims D-Bus (logind, hostnamed, …)
|
||||||
/ente/seed.card.json Tarjeta Semilla canónica
|
/ente/seed.card.json Tarjeta Semilla canónica
|
||||||
/bin/{sh,ls,mount,…} busybox-static (o glibc dinámica + libs)
|
/bin/{sh,ls,mount,…} busybox-static
|
||||||
/etc, /dev, /proc, /sys, /run mountpoints vacíos
|
/etc, /dev, /proc, /sys, /run mountpoints vacíos
|
||||||
/sys/fs/cgroup mountpoint cgroup v2
|
/sys/fs/cgroup mountpoint cgroup v2
|
||||||
```
|
```
|
||||||
@@ -38,31 +38,69 @@ Path canónico de la semilla en **prod**: `/ente/seed.card.json` (ver
|
|||||||
|
|
||||||
## 2. Build del initrd
|
## 2. Build del initrd
|
||||||
|
|
||||||
Requisitos host: `cargo`, `cpio`, `gzip`, y opcionalmente `busybox-static`
|
### 2a. Por qué musl-static
|
||||||
(en Debian/Ubuntu: `apt install busybox-static`).
|
|
||||||
|
`ente-zero` corre como **PID 1**: si tiene cualquier dependencia dinámica
|
||||||
|
(`libgcc_s.so.1`, `libc.so.6`, `ld-linux-x86-64.so.2`) que no está
|
||||||
|
presente en el initramfs, el kernel paniquea con
|
||||||
|
`error while loading shared libraries: libgcc_s.so.1`.
|
||||||
|
|
||||||
|
Solución estándar: compilar contra el target `x86_64-unknown-linux-musl`,
|
||||||
|
que produce un ELF **totalmente estático** (no necesita libc ni
|
||||||
|
intérprete en runtime). Es el default del script.
|
||||||
|
|
||||||
|
### 2b. Requisitos del host
|
||||||
|
|
||||||
|
- `rust toolchain` con el target musl:
|
||||||
|
```bash
|
||||||
|
rustup target add x86_64-unknown-linux-musl
|
||||||
|
```
|
||||||
|
- `musl-gcc` para crates con `build.rs` C (sled, blake3, etc.):
|
||||||
|
```bash
|
||||||
|
apt install musl-tools # Debian/Ubuntu
|
||||||
|
apk add musl-dev gcc # Alpine
|
||||||
|
pacman -S musl # Arch
|
||||||
|
```
|
||||||
|
- `cpio`, `gzip` para empaquetar.
|
||||||
|
- `busybox-static` para el userspace mínimo dentro del initramfs:
|
||||||
|
```bash
|
||||||
|
apt install busybox-static # Debian/Ubuntu
|
||||||
|
# Alpine ya trae busybox built-in
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2c. Invocación
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Default: semilla de prod, sale en out/arje.initrd.cpio.gz
|
# Default: musl-static, semilla de prod, sale en out/arje.initrd.cpio.gz
|
||||||
scripts/build-arje-initrd.sh
|
scripts/build-arje-initrd.sh
|
||||||
|
|
||||||
# Customizar:
|
# Customizar seed/salida:
|
||||||
scripts/build-arje-initrd.sh seeds/arje-minimal.card.json out/min.cpio.gz
|
scripts/build-arje-initrd.sh seeds/arje-minimal.card.json out/min.cpio.gz
|
||||||
|
|
||||||
# Sin busybox del sistema, apuntar a uno propio:
|
# busybox-static no está en $PATH:
|
||||||
BUSYBOX_BIN=/path/to/busybox scripts/build-arje-initrd.sh
|
BUSYBOX_BIN=/path/to/busybox scripts/build-arje-initrd.sh
|
||||||
|
|
||||||
# Vendorear binarios extra (separados por espacio):
|
# Vendorear binarios extra estáticos:
|
||||||
EXTRA_BINS="/usr/bin/strace /usr/bin/gdb" scripts/build-arje-initrd.sh
|
EXTRA_BINS="/usr/local/bin/strace-static" scripts/build-arje-initrd.sh
|
||||||
|
|
||||||
|
# (NO RECOMENDADO) build glibc dinámico — kernel panic asegurado salvo que
|
||||||
|
# vendorees libgcc_s + libc + ld-linux a mano:
|
||||||
|
ARJE_TARGET=x86_64-unknown-linux-gnu scripts/build-arje-initrd.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
El script:
|
### 2d. Qué hace el script
|
||||||
|
|
||||||
1. Corre `cargo build --release` para `ente-zero` + los 14 shims compat.
|
1. Verifica que el target musl esté instalado; si no, da el comando
|
||||||
2. Valida la seed con `seeds/validate.sh` (parse + `Card::validate`).
|
exacto para instalarlo.
|
||||||
3. Stage en un tmpdir → copia binarios + crea mountpoints + escribe `/init`.
|
2. `cargo build --release --target x86_64-unknown-linux-musl` para
|
||||||
4. Empaqueta `find . | cpio -o -H newc | gzip -9`.
|
`ente-zero` + los 14 shims compat.
|
||||||
|
3. Sanity-check con `file`: aborta si algún binario quedó dinámico.
|
||||||
|
4. Valida la seed con `seeds/validate.sh` (parse + `Card::validate`).
|
||||||
|
5. Verifica que `busybox` sea estático (también aborta si es dinámico).
|
||||||
|
6. Stage en un tmpdir → copia binarios + crea mountpoints + escribe `/init`.
|
||||||
|
7. Empaqueta `find . | cpio -o -H newc | gzip -9`.
|
||||||
|
|
||||||
Tamaño típico: ~15-25 MB descomprimido, 5-8 MB el `.cpio.gz`.
|
Tamaño típico (musl): ~10-15 MB descomprimido, 4-6 MB el `.cpio.gz`.
|
||||||
|
|
||||||
## 3. Boot en QEMU
|
## 3. Boot en QEMU
|
||||||
|
|
||||||
@@ -302,11 +340,83 @@ mkdir /tmp/arje-test && cp seeds/arje-minimal.card.json /tmp/arje-test/seed.card
|
|||||||
cd /tmp/arje-test && target/release/ente-zero
|
cd /tmp/arje-test && target/release/ente-zero
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## 7. Troubleshooting
|
||||||
|
|
||||||
|
### 7a. `error while loading shared libraries: libgcc_s.so.1` al boot
|
||||||
|
|
||||||
|
**Causa**: el `/sbin/ente-zero` del initrd se compiló contra glibc
|
||||||
|
(`x86_64-unknown-linux-gnu`) y depende dinámicamente de `libgcc_s.so.1`,
|
||||||
|
`libc.so.6`, `ld-linux-x86-64.so.2`. Esas libs no están en el initramfs,
|
||||||
|
el kernel mata PID 1 → panic.
|
||||||
|
|
||||||
|
**Fix**: usar el target musl (default del script desde mayo 2026):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
rustup target add x86_64-unknown-linux-musl
|
||||||
|
apt install musl-tools # Debian/Ubuntu — para crates con build.rs C
|
||||||
|
scripts/build-arje-initrd.sh # ya usa musl por default
|
||||||
|
```
|
||||||
|
|
||||||
|
Verificar manualmente que el binario quedó estático:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
file target/x86_64-unknown-linux-musl/release/ente-zero
|
||||||
|
# → "ELF 64-bit LSB executable, ..., statically linked, ..."
|
||||||
|
```
|
||||||
|
|
||||||
|
Si decidís quedarte en glibc dinámico, hay que vendorear `libgcc_s.so.1`,
|
||||||
|
`libc.so.6` y `ld-linux-x86-64.so.2` (más cualquier dep de `tracing` y
|
||||||
|
`tokio`) bajo `/lib64/` y `/lib/x86_64-linux-gnu/` del initrd. No
|
||||||
|
recomendado.
|
||||||
|
|
||||||
|
### 7b. Kernel panic: `Kernel panic - not syncing: Attempted to kill init!`
|
||||||
|
|
||||||
|
**Causa**: `ente-zero` salió con error antes de bind del bus, o `/init`
|
||||||
|
crashed antes de exec. PID 1 muriendo = panic kernel.
|
||||||
|
|
||||||
|
**Fix**: agregar `panic=10` al cmdline (ya está en el script) para
|
||||||
|
auto-reboot tras 10 s y ver el error. Bajo QEMU, `-no-reboot` lo
|
||||||
|
convierte en exit limpio. Capturar el log:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
HEADLESS=1 scripts/run-arje-qemu.sh 2>&1 | tee /tmp/arje-boot.log
|
||||||
|
```
|
||||||
|
|
||||||
|
Buscar la línea anterior a `Attempted to kill init`.
|
||||||
|
|
||||||
|
### 7c. `seed inválida` al correr build-arje-initrd.sh
|
||||||
|
|
||||||
|
**Causa**: el JSON tiene un ULID con caracteres prohibidos (`I L O U`
|
||||||
|
están **excluidos** de Crockford base32), un `Payload::Native.exec`
|
||||||
|
vacío, o un campo del schema rechazado por `brahman_card::Card::validate`.
|
||||||
|
|
||||||
|
**Fix**: correr el validador directo para ver el error completo:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
seeds/validate.sh seeds/mi-seed.card.json
|
||||||
|
# Si falla, las primeras 40 líneas del log van a stderr.
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7d. `cannot find -lcrypt` o `cannot find -lpam` al compilar musl
|
||||||
|
|
||||||
|
**Causa**: algún crate del workspace pulled in una dep C que no
|
||||||
|
encontró su lib bajo musl.
|
||||||
|
|
||||||
|
**Fix**: para los crates de arje no debería pasar (revisamos las deps).
|
||||||
|
Si ocurre con un crate nuevo, suele resolverse con `RUSTFLAGS="-C
|
||||||
|
target-feature=+crt-static"` o aislando el feature problemático.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Apéndice — checklist pre-deploy
|
## Apéndice — checklist pre-deploy
|
||||||
|
|
||||||
- [ ] `cargo build --release -p ente-zero` sin warnings.
|
- [ ] `rustup target add x86_64-unknown-linux-musl` instalado en el host build.
|
||||||
|
- [ ] `musl-tools` (Debian/Ubuntu) o equivalente disponible.
|
||||||
|
- [ ] `busybox-static` disponible para vendorear userspace.
|
||||||
|
- [ ] `cargo build --release --target x86_64-unknown-linux-musl -p ente-zero`
|
||||||
|
compila sin warnings.
|
||||||
|
- [ ] `file target/x86_64-unknown-linux-musl/release/ente-zero` reporta
|
||||||
|
"statically linked".
|
||||||
- [ ] `seeds/validate.sh seeds/arje-prod.card.json` → OK.
|
- [ ] `seeds/validate.sh seeds/arje-prod.card.json` → OK.
|
||||||
- [ ] `scripts/build-arje-initrd.sh` produce `out/arje.initrd.cpio.gz`.
|
- [ ] `scripts/build-arje-initrd.sh` produce `out/arje.initrd.cpio.gz`.
|
||||||
- [ ] `scripts/run-arje-qemu.sh` arranca y muestra `Tarjeta Semilla cargada
|
- [ ] `scripts/run-arje-qemu.sh` arranca y muestra `Tarjeta Semilla cargada
|
||||||
|
|||||||
+105
-22
@@ -2,13 +2,18 @@
|
|||||||
# build-arje-initrd.sh — empaqueta ente-zero + shims compat + Tarjeta Semilla
|
# build-arje-initrd.sh — empaqueta ente-zero + shims compat + Tarjeta Semilla
|
||||||
# en un initramfs CPIO+gzip listo para arrancar bajo QEMU o como /init real.
|
# en un initramfs CPIO+gzip listo para arrancar bajo QEMU o como /init real.
|
||||||
#
|
#
|
||||||
|
# Toolchain: musl-static por default. ente-zero es PID 1; cualquier
|
||||||
|
# dependencia dinámica (libgcc_s, libc.so.6, ld-linux) que no esté en el
|
||||||
|
# initramfs produce kernel panic. Compilar contra musl elimina el problema
|
||||||
|
# completamente — un solo ELF estático.
|
||||||
|
#
|
||||||
# Layout del initrd resultante:
|
# Layout del initrd resultante:
|
||||||
# /init → wrapper sh que exec /sbin/ente-zero
|
# /init → wrapper sh que exec /sbin/ente-zero
|
||||||
# /sbin/ente-zero → PID 1
|
# /sbin/ente-zero → PID 1 (musl-static)
|
||||||
# /usr/sbin/ente-*-compat → shims systemd
|
# /usr/sbin/ente-*-compat → shims systemd (musl-static)
|
||||||
# /usr/sbin/ente-echo, ente-policy-provider
|
# /usr/sbin/ente-echo, ente-policy-provider
|
||||||
# /ente/seed.card.json → Tarjeta Semilla
|
# /ente/seed.card.json → Tarjeta Semilla
|
||||||
# /bin/{sh,ls,cat,...} → busybox o glibc-static (depende del flag)
|
# /bin/{sh,ls,cat,...} → busybox-static (recomendado)
|
||||||
# /dev, /proc, /sys, /run → puntos de montaje (ente-zero los monta)
|
# /dev, /proc, /sys, /run → puntos de montaje (ente-zero los monta)
|
||||||
#
|
#
|
||||||
# Uso:
|
# Uso:
|
||||||
@@ -18,15 +23,30 @@
|
|||||||
# out default: out/arje.initrd.cpio.gz
|
# out default: out/arje.initrd.cpio.gz
|
||||||
#
|
#
|
||||||
# Env:
|
# Env:
|
||||||
# BUSYBOX_BIN path a un busybox-static (default: $(which busybox))
|
# ARJE_TARGET triple de cargo (default: x86_64-unknown-linux-musl).
|
||||||
# EXTRA_BINS binarios extra a copiar, separados por espacio
|
# Para glibc dinámica usar x86_64-unknown-linux-gnu — en
|
||||||
|
# ese caso hay que vendorear libgcc_s.so.1 + libc.so.6 +
|
||||||
|
# ld-linux-x86-64.so.2 manualmente o el kernel paniquea.
|
||||||
|
# BUSYBOX_BIN path a un busybox-static. Default: busca `busybox` en PATH.
|
||||||
|
# EXTRA_BINS binarios extra a copiar (deben ser estáticos), space-separated.
|
||||||
#
|
#
|
||||||
# Requisitos: cpio, gzip, ldd (sólo si no usás busybox-static).
|
# Requisitos del host:
|
||||||
|
# - rust toolchain con el target musl instalado:
|
||||||
|
# rustup target add x86_64-unknown-linux-musl
|
||||||
|
# - musl-gcc para algunos crates con build.rs C (sled, etc.):
|
||||||
|
# Debian/Ubuntu: apt install musl-tools
|
||||||
|
# Alpine: apk add musl-dev gcc
|
||||||
|
# Arch: pacman -S musl
|
||||||
|
# - cpio, gzip.
|
||||||
|
# - busybox-static (recomendado, opcional):
|
||||||
|
# Debian/Ubuntu: apt install busybox-static
|
||||||
|
# Alpine: (busybox viene built-in)
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
SEED="${1:-seeds/arje-prod.card.json}"
|
SEED="${1:-seeds/arje-prod.card.json}"
|
||||||
OUT="${2:-out/arje.initrd.cpio.gz}"
|
OUT="${2:-out/arje.initrd.cpio.gz}"
|
||||||
|
TARGET="${ARJE_TARGET:-x86_64-unknown-linux-musl}"
|
||||||
BUSYBOX_BIN="${BUSYBOX_BIN:-$(command -v busybox 2>/dev/null || true)}"
|
BUSYBOX_BIN="${BUSYBOX_BIN:-$(command -v busybox 2>/dev/null || true)}"
|
||||||
EXTRA_BINS="${EXTRA_BINS:-}"
|
EXTRA_BINS="${EXTRA_BINS:-}"
|
||||||
|
|
||||||
@@ -39,9 +59,40 @@ if [ ! -f "$SEED" ]; then
|
|||||||
exit 2
|
exit 2
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# 1. Build release de ente-zero y todos los compat shims.
|
# Chequeo del target: si es musl, debe estar instalado. Mensaje accionable
|
||||||
echo "[build-initrd] cargo build --release de ente-zero + shims"
|
# cuando falta — la causa #1 de fracaso al primer intento.
|
||||||
cargo build --release \
|
if [[ "$TARGET" == *-musl ]]; then
|
||||||
|
RUSTLIB="$(rustc --print sysroot 2>/dev/null)/lib/rustlib/$TARGET"
|
||||||
|
if [ ! -d "$RUSTLIB" ]; then
|
||||||
|
cat >&2 <<EOF
|
||||||
|
[build-initrd] target musl no instalado: $TARGET
|
||||||
|
|
||||||
|
Instalalo con uno de:
|
||||||
|
|
||||||
|
# Si tenés rustup:
|
||||||
|
rustup target add $TARGET
|
||||||
|
|
||||||
|
# Si tu rust viene del paquete del sistema (Debian/Ubuntu):
|
||||||
|
apt install rustup && rustup default stable && rustup target add $TARGET
|
||||||
|
|
||||||
|
Y asegurate de tener musl-gcc para los crates con build.rs C:
|
||||||
|
|
||||||
|
apt install musl-tools # Debian/Ubuntu
|
||||||
|
apk add musl-dev gcc # Alpine
|
||||||
|
pacman -S musl # Arch
|
||||||
|
|
||||||
|
Si querés saltar musl (NO recomendado para PID 1, te dará kernel panic
|
||||||
|
por libgcc_s.so.1 faltante a menos que la vendorees):
|
||||||
|
|
||||||
|
ARJE_TARGET=x86_64-unknown-linux-gnu scripts/build-arje-initrd.sh
|
||||||
|
EOF
|
||||||
|
exit 5
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 1. Build release de ente-zero y todos los compat shims con el target elegido.
|
||||||
|
echo "[build-initrd] cargo build --release --target $TARGET de ente-zero + shims"
|
||||||
|
cargo build --release --target "$TARGET" \
|
||||||
-p ente-zero \
|
-p ente-zero \
|
||||||
-p ente-echo \
|
-p ente-echo \
|
||||||
-p ente-logind-compat \
|
-p ente-logind-compat \
|
||||||
@@ -59,33 +110,63 @@ cargo build --release \
|
|||||||
-p ente-binfmt-compat \
|
-p ente-binfmt-compat \
|
||||||
-p ente-policy-provider
|
-p ente-policy-provider
|
||||||
|
|
||||||
# 2. Validar la seed.
|
BIN_DIR="target/$TARGET/release"
|
||||||
|
|
||||||
|
# 2. Validar la seed. validate.sh corre el binario del host (release plain),
|
||||||
|
# sólo verifica el schema — independiente del target.
|
||||||
if ! seeds/validate.sh "$SEED" >/dev/null 2>&1; then
|
if ! seeds/validate.sh "$SEED" >/dev/null 2>&1; then
|
||||||
echo "[build-initrd] seed inválida: $SEED" >&2
|
echo "[build-initrd] seed inválida: $SEED" >&2
|
||||||
exit 3
|
exit 3
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# 3. Stage root del initrd.
|
# 3. Sanity check: si compilamos musl, los ELF deben ser ESTÁTICOS.
|
||||||
|
# Si quedó alguno con interpreter dinámico, el kernel paniquea.
|
||||||
|
if [[ "$TARGET" == *-musl ]] && command -v file >/dev/null 2>&1; then
|
||||||
|
bad=0
|
||||||
|
for b in "$BIN_DIR/ente-zero" "$BIN_DIR/ente-echo"; do
|
||||||
|
[ -f "$b" ] || continue
|
||||||
|
if file "$b" | grep -q "dynamically linked"; then
|
||||||
|
echo "[build-initrd] WARN: $b quedó DYNAMIC (esperábamos static):" >&2
|
||||||
|
file "$b" >&2
|
||||||
|
bad=$((bad + 1))
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if [ "$bad" -gt 0 ]; then
|
||||||
|
echo "[build-initrd] abortando — un binario PID-1 dinámico paniquea el kernel" >&2
|
||||||
|
exit 6
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 4. Stage root del initrd.
|
||||||
STAGE="$(mktemp -d -t arje-initrd.XXXXXX)"
|
STAGE="$(mktemp -d -t arje-initrd.XXXXXX)"
|
||||||
trap 'rm -rf "$STAGE"' EXIT
|
trap 'rm -rf "$STAGE"' EXIT
|
||||||
mkdir -p "$STAGE"/{bin,sbin,usr/sbin,etc,ente,proc,sys,dev,run,tmp,sys/fs/cgroup}
|
mkdir -p "$STAGE"/{bin,sbin,usr/sbin,etc,ente,proc,sys,dev,run,tmp,sys/fs/cgroup}
|
||||||
|
|
||||||
# 4. Copiar binarios arje.
|
# 5. Copiar binarios arje.
|
||||||
install -m 0755 target/release/ente-zero "$STAGE/sbin/ente-zero"
|
install -m 0755 "$BIN_DIR/ente-zero" "$STAGE/sbin/ente-zero"
|
||||||
for b in ente-echo ente-policy-provider \
|
for b in ente-echo ente-policy-provider \
|
||||||
ente-logind-compat ente-hostnamed-compat ente-timedated-compat \
|
ente-logind-compat ente-hostnamed-compat ente-timedated-compat \
|
||||||
ente-localed-compat ente-journald-compat ente-resolved-compat \
|
ente-localed-compat ente-journald-compat ente-resolved-compat \
|
||||||
ente-polkit-compat ente-machined-compat ente-systemd1-compat \
|
ente-polkit-compat ente-machined-compat ente-systemd1-compat \
|
||||||
ente-notify-compat ente-timer-compat ente-tmpfiles-compat \
|
ente-notify-compat ente-timer-compat ente-tmpfiles-compat \
|
||||||
ente-binfmt-compat; do
|
ente-binfmt-compat; do
|
||||||
install -m 0755 "target/release/$b" "$STAGE/usr/sbin/$b"
|
install -m 0755 "$BIN_DIR/$b" "$STAGE/usr/sbin/$b"
|
||||||
done
|
done
|
||||||
|
|
||||||
# 5. Userspace mínimo (sh, ls, mount, mkdir, ...). Dos rutas:
|
# 6. Userspace mínimo. Con binarios musl-static no necesitamos vendorear
|
||||||
|
# libc/ld-linux. Las dos rutas:
|
||||||
# (a) busybox-static apuntado por $BUSYBOX_BIN → 1 binario, todo simlink.
|
# (a) busybox-static apuntado por $BUSYBOX_BIN → 1 binario, todo simlink.
|
||||||
# (b) sin busybox → copiar /bin/sh + deps con ldd (libc dinámica).
|
# (b) sin busybox → copiar /bin/sh + sus deps via ldd. Sólo seguro si el
|
||||||
|
# /bin/sh del host es estático (ej. dash en algunos distros NO lo es).
|
||||||
if [ -n "$BUSYBOX_BIN" ] && [ -x "$BUSYBOX_BIN" ]; then
|
if [ -n "$BUSYBOX_BIN" ] && [ -x "$BUSYBOX_BIN" ]; then
|
||||||
echo "[build-initrd] usando busybox-static: $BUSYBOX_BIN"
|
echo "[build-initrd] usando busybox-static: $BUSYBOX_BIN"
|
||||||
|
# Validar que el busybox es realmente estático (causa frecuente de panic).
|
||||||
|
if command -v file >/dev/null 2>&1 && \
|
||||||
|
file "$BUSYBOX_BIN" | grep -q "dynamically linked"; then
|
||||||
|
echo "[build-initrd] ERROR: $BUSYBOX_BIN es dinámico — necesitás busybox-static" >&2
|
||||||
|
echo " apt install busybox-static # Debian/Ubuntu" >&2
|
||||||
|
exit 7
|
||||||
|
fi
|
||||||
install -m 0755 "$BUSYBOX_BIN" "$STAGE/bin/busybox"
|
install -m 0755 "$BUSYBOX_BIN" "$STAGE/bin/busybox"
|
||||||
( cd "$STAGE/bin" && for app in sh ls cat mount umount mkdir cp mv \
|
( cd "$STAGE/bin" && for app in sh ls cat mount umount mkdir cp mv \
|
||||||
echo grep sed awk ps kill sleep insmod modprobe poweroff reboot \
|
echo grep sed awk ps kill sleep insmod modprobe poweroff reboot \
|
||||||
@@ -93,8 +174,9 @@ if [ -n "$BUSYBOX_BIN" ] && [ -x "$BUSYBOX_BIN" ]; then
|
|||||||
ln -sf busybox "$app"
|
ln -sf busybox "$app"
|
||||||
done )
|
done )
|
||||||
else
|
else
|
||||||
echo "[build-initrd] sin busybox — copiando /bin/sh + deps via ldd"
|
echo "[build-initrd] WARN: sin busybox-static — vendoreando /bin/sh + libs via ldd"
|
||||||
install -m 0755 /bin/sh "$STAGE/bin/sh"
|
echo " Esto es FRÁGIL. Instalá busybox-static y reintentá:"
|
||||||
|
echo " apt install busybox-static # Debian/Ubuntu"
|
||||||
copy_lib() {
|
copy_lib() {
|
||||||
local lib="$1"
|
local lib="$1"
|
||||||
[ -f "$lib" ] || return 0
|
[ -f "$lib" ] || return 0
|
||||||
@@ -111,10 +193,10 @@ else
|
|||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# 6. Tarjeta Semilla. Path canónico en prod: /ente/seed.card.json
|
# 7. Tarjeta Semilla. Path canónico en prod: /ente/seed.card.json
|
||||||
install -m 0644 "$SEED" "$STAGE/ente/seed.card.json"
|
install -m 0644 "$SEED" "$STAGE/ente/seed.card.json"
|
||||||
|
|
||||||
# 7. /init wrapper. El kernel pasa control a /init; nosotros invocamos
|
# 8. /init wrapper. El kernel pasa control a /init; nosotros invocamos
|
||||||
# ente-zero como PID 1 real con su env mínimo.
|
# ente-zero como PID 1 real con su env mínimo.
|
||||||
cat > "$STAGE/init" <<'EOF'
|
cat > "$STAGE/init" <<'EOF'
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
@@ -126,7 +208,7 @@ exec /sbin/ente-zero
|
|||||||
EOF
|
EOF
|
||||||
chmod 0755 "$STAGE/init"
|
chmod 0755 "$STAGE/init"
|
||||||
|
|
||||||
# 8. Binarios extra a vendorear.
|
# 9. Binarios extra a vendorear (deben ser estáticos).
|
||||||
if [ -n "$EXTRA_BINS" ]; then
|
if [ -n "$EXTRA_BINS" ]; then
|
||||||
for b in $EXTRA_BINS; do
|
for b in $EXTRA_BINS; do
|
||||||
[ -x "$b" ] || { echo "[build-initrd] EXTRA_BINS: $b no existe"; exit 4; }
|
[ -x "$b" ] || { echo "[build-initrd] EXTRA_BINS: $b no existe"; exit 4; }
|
||||||
@@ -134,7 +216,8 @@ if [ -n "$EXTRA_BINS" ]; then
|
|||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# 9. Empaquetar CPIO + gzip. Formato newc (estándar para Linux initramfs).
|
# 10. Empaquetar CPIO + gzip. Formato newc (estándar para Linux initramfs).
|
||||||
mkdir -p "$(dirname "$OUT")"
|
mkdir -p "$(dirname "$OUT")"
|
||||||
( cd "$STAGE" && find . -print0 | cpio -o -H newc --null --quiet ) | gzip -9 > "$OUT"
|
( cd "$STAGE" && find . -print0 | cpio -o -H newc --null --quiet ) | gzip -9 > "$OUT"
|
||||||
echo "[build-initrd] generado: $OUT ($(du -h "$OUT" | cut -f1))"
|
echo "[build-initrd] generado: $OUT ($(du -h "$OUT" | cut -f1))"
|
||||||
|
echo "[build-initrd] target: $TARGET"
|
||||||
|
|||||||
Reference in New Issue
Block a user