Cierra el lazo ISO live -> disco instalado -> bootea solo. iso-image.sh INSTALLER=1 bundlea kernel + GRUB MBR (boot/core.img + modulos) en el initramfs bajo /usr/lib/hammer/install/ + inyecta /usr/bin/hammer-install. hammer-install corre dentro del live como root real (busybox fdisk/mke2fs/mount/dd + uutils cp): particiona MBR (/,/store,/var/lib/hammer), formatea, copia la propia raiz del live (autoinstalador), escribe /boot+wrapper, instala GRUB con 2 dd (boot->MBR, core->hueco post-MBR; punteros default 1/2 ya valen en MBR contiguo, sin parcheo). AUTO_INSTALL=<dev> = /init desatendido (install+poweroff). iso-install-test.sh valida E2E: ISO+disco blanco -> HAMMER-INSTALL-OK -> boot del disco solo -> GRUB->kernel->arje-zero->sshd, particiones dedicadas montadas. GOTCHAS: busybox fdisk CHS-alinea a 63 (hueco 62 < core 281 sectores) -> pisa el FS de p1 -> grub>; fix sectores explicitos (p1@2048). Copiar top-level de / enumerado, no lista fija, o se escapa /ente/seed.card.json. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
154 lines
7.8 KiB
Bash
Executable File
154 lines
7.8 KiB
Bash
Executable File
#!/bin/sh
|
|
# iso-image.sh — Etapa E5 (SDD 13): produce un MEDIO LIVE booteable como ISO 9660 / El Torito.
|
|
#
|
|
# A diferencia de install-image.sh (E1, disco GPT con / persistente en vda2), un medio live arranca
|
|
# ENTERO desde RAM: GRUB (El Torito) carga kernel + initramfs desde el ISO 9660, el kernel desempaqueta
|
|
# el initramfs (el rootfs del producto) a un tmpfs y corre /init — sin tocar disco. Es el medio para
|
|
# correr el instalador (`hammer install /dev/sdX`) en hardware nuevo, o para probar el sistema sin
|
|
# instalarlo.
|
|
#
|
|
# El ISO lo ARMA `xorriso` construido por hammer desde fuente (recipes/xorriso.toml) — el host no lo
|
|
# trae. La cadena de boot BIOS reusa los módulos GRUB i386-pc de E1, pero con el core El Torito
|
|
# (formato i386-pc-eltorito + iso9660) en vez del core de disco (ext2 + biosdisk).
|
|
#
|
|
# Cadena: SeaBIOS → El Torito boot catalog → eltorito.img (cdboot+core GRUB) → lee (cd0)/boot/grub/
|
|
# grub.cfg → `linux /boot/bzImage rdinit=/init` + `initrd /boot/initramfs.cpio.gz` → kernel desempaqueta
|
|
# → /init (marcador + exec del init real del rootfs).
|
|
#
|
|
# Uso:
|
|
# ./scripts/iso-image.sh # crea work/hammer-live.iso
|
|
# BOOT=1 KVM=1 ./scripts/iso-image.sh # además lo arranca desde el CD (auto-boot)
|
|
#
|
|
# Variables:
|
|
# ROOTFS dir rootfs a empaquetar como initramfs (default work/builder-rootfs)
|
|
# KERNEL bzImage a embeber (default store/*-linux/boot/bzImage)
|
|
# ISO ISO de salida (default work/hammer-live.iso)
|
|
# XORRISO binario xorriso (default el del store; si no, host)
|
|
# GRUB_LIB módulos GRUB i386-pc (default /usr/lib/grub/i386-pc)
|
|
# CMDLINE cmdline del kernel (default "console=ttyS0 rdinit=/init")
|
|
# BOOT/KVM/MEM passthrough al arranque de prueba
|
|
set -eu
|
|
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
|
cd "$ROOT"
|
|
|
|
ROOTFS="${ROOTFS:-work/builder-rootfs}"
|
|
ISO="${ISO:-work/hammer-live.iso}"
|
|
KERNEL="${KERNEL:-$(ls store/*-linux/boot/bzImage 2>/dev/null | head -1)}"
|
|
GRUB_LIB="${GRUB_LIB:-/usr/lib/grub/i386-pc}"
|
|
CMDLINE="${CMDLINE:-console=ttyS0 rdinit=/init}"
|
|
# xorriso: preferimos el construido por hammer (dogfooding de recipes/xorriso.toml); fallback al host.
|
|
XORRISO="${XORRISO:-$(ls store/*-xorriso/usr/bin/xorriso 2>/dev/null | head -1)}"
|
|
[ -n "$XORRISO" ] && [ -x "$XORRISO" ] || XORRISO="$(command -v xorriso 2>/dev/null || true)"
|
|
|
|
[ -d "$ROOTFS" ] || { echo "no existe ROOTFS: $ROOTFS" >&2; exit 1; }
|
|
[ -e "$ROOTFS/sbin/init" ] || { echo "ROOTFS sin /sbin/init" >&2; exit 1; }
|
|
[ -n "$KERNEL" ] && [ -r "$KERNEL" ] || { echo "no encuentro el kernel (set KERNEL=<bzImage>)" >&2; exit 1; }
|
|
[ -n "$XORRISO" ] || { echo "no encuentro xorriso (build recipes/xorriso.toml)" >&2; exit 1; }
|
|
[ -d "$GRUB_LIB" ] && [ -r "$GRUB_LIB/cdboot.img" ] || { echo "faltan módulos GRUB i386-pc en $GRUB_LIB" >&2; exit 1; }
|
|
command -v grub-mkimage >/dev/null 2>&1 || { echo "falta grub-mkimage" >&2; exit 1; }
|
|
command -v cpio >/dev/null 2>&1 || { echo "falta cpio" >&2; exit 1; }
|
|
|
|
echo "==> xorriso: $XORRISO ($("$XORRISO" -version 2>&1 | grep -m1 'xorriso version' || echo '?'))"
|
|
|
|
STAGE="work/.iso-stage"
|
|
rm -rf "$STAGE"
|
|
ISO_ROOT="$STAGE/iso"
|
|
RFS="$STAGE/rfs"
|
|
mkdir -p "$ISO_ROOT/boot/grub/i386-pc" "$RFS"
|
|
|
|
# --- initramfs: rootfs (hardlinks) + /init marcador que arranca el init real ---
|
|
echo "==> staging initramfs desde $ROOTFS (hardlinks) + /init marcador"
|
|
cp -al "$ROOTFS" "$RFS/root"
|
|
# El cpio se arma desde $RFS/root; inyectamos /init ahí (rdinit=/init lo busca en la raíz del initramfs).
|
|
# /init del medio live: monta lo básico + marcador. Con AUTO_INSTALL=<dev>, instala desatendido a ese
|
|
# disco y apaga (instalación unattended + scaffolding del test); si no, arranca el init real (live).
|
|
{
|
|
echo '#!/bin/sh'
|
|
echo '# /init del medio live (Etapa E5).'
|
|
echo '/bin/busybox mount -t proc proc /proc 2>/dev/null || true'
|
|
echo '/bin/busybox mount -t sysfs sys /sys 2>/dev/null || true'
|
|
echo '/bin/busybox mount -t devtmpfs dev /dev 2>/dev/null || true'
|
|
echo 'echo "HAMMER-ISO-LIVE-OK: medio live arrancado desde El Torito"'
|
|
if [ -n "${AUTO_INSTALL:-}" ]; then
|
|
echo "echo 'HAMMER-AUTO-INSTALL: instalando a ${AUTO_INSTALL}'"
|
|
echo "if /usr/bin/hammer-install '${AUTO_INSTALL}'; then echo 'HAMMER-INSTALL-OK'; else echo 'HAMMER-INSTALL-FAIL'; fi"
|
|
echo '/bin/busybox sync'
|
|
echo '/bin/busybox poweroff -f'
|
|
else
|
|
echo 'exec /sbin/init'
|
|
fi
|
|
} > "$RFS/root/init"
|
|
chmod +x "$RFS/root/init"
|
|
|
|
# --- INSTALLER=1: payload de instalación a disco DESDE el live (refinamiento #1) ---
|
|
# Bundle kernel + GRUB (boot.img + core.img MBR-prefix + módulos) bajo /usr/lib/hammer/install/ y el
|
|
# instalador en /usr/bin/hammer-install. El core.img se arma acá (build-time, el host tiene
|
|
# grub-mkimage); el live NO lo necesita — sólo dd's. core prefix (hd0,msdos1)/boot/grub para boot MBR.
|
|
if [ "${INSTALLER:-0}" = 1 ]; then
|
|
echo "==> INSTALLER=1: bundling payload de instalación a disco (kernel + GRUB MBR + hammer-install)"
|
|
IPL="$RFS/root/usr/lib/hammer/install"
|
|
mkdir -p "$IPL/grub/i386-pc" "$IPL/kernel"
|
|
cp "$KERNEL" "$IPL/kernel/bzImage"; chmod 0644 "$IPL/kernel/bzImage"
|
|
cp "$GRUB_LIB/boot.img" "$IPL/grub/boot.img"
|
|
cp "$GRUB_LIB"/*.mod "$GRUB_LIB"/*.lst "$IPL/grub/i386-pc/" 2>/dev/null || true
|
|
# core.img para disco MBR: prefix a la 1ª partición msdos, módulos de disco (biosdisk/part_msdos/ext2).
|
|
grub-mkimage -O i386-pc -p '(hd0,msdos1)/boot/grub' -o "$IPL/grub/core.img" \
|
|
biosdisk part_msdos ext2 normal configfile linux echo ls boot search
|
|
install -m 0755 "$ROOT/scripts/hammer-live-install.sh" "$RFS/root/usr/bin/hammer-install"
|
|
fi
|
|
|
|
echo "==> empaquetando initramfs.cpio.gz"
|
|
( cd "$RFS/root" && find . -print0 | cpio --null -o -H newc -R 0:0 2>/dev/null | gzip -1 ) > "$ISO_ROOT/boot/initramfs.cpio.gz"
|
|
|
|
# --- kernel + módulos GRUB + grub.cfg en el árbol del ISO ---
|
|
cp "$KERNEL" "$ISO_ROOT/boot/bzImage"; chmod 0644 "$ISO_ROOT/boot/bzImage"
|
|
cp "$GRUB_LIB"/*.mod "$GRUB_LIB"/*.lst "$ISO_ROOT/boot/grub/i386-pc/" 2>/dev/null || true
|
|
cat > "$ISO_ROOT/boot/grub/grub.cfg" <<CFG
|
|
set timeout=2
|
|
set default=0
|
|
serial --unit=0 --speed=115200
|
|
terminal_input serial console
|
|
terminal_output serial console
|
|
insmod iso9660
|
|
insmod normal
|
|
menuentry "hammer (live)" {
|
|
linux /boot/bzImage $CMDLINE
|
|
initrd /boot/initramfs.cpio.gz
|
|
}
|
|
CFG
|
|
|
|
# --- core GRUB El Torito: igual que el de disco pero con iso9660+biosdisk en vez de ext2 ---
|
|
echo "==> grub-mkimage El Torito (formato i386-pc-eltorito, módulos iso9660)"
|
|
grub-mkimage -O i386-pc-eltorito -p '/boot/grub' -o "$ISO_ROOT/boot/grub/i386-pc/eltorito.img" \
|
|
biosdisk iso9660 part_gpt part_msdos normal configfile linux echo ls boot search
|
|
|
|
# --- armar el ISO con xorriso (personalidad mkisofs), El Torito + isohybrid MBR ---
|
|
echo "==> xorriso: armando $ISO (El Torito BIOS + isohybrid MBR)"
|
|
rm -f "$ISO"
|
|
MBR_ARGS=""
|
|
[ -r "$GRUB_LIB/boot_hybrid.img" ] && MBR_ARGS="--grub2-mbr $GRUB_LIB/boot_hybrid.img"
|
|
# shellcheck disable=SC2086
|
|
"$XORRISO" -as mkisofs \
|
|
-volid HAMMER_LIVE \
|
|
-graft-points \
|
|
$MBR_ARGS \
|
|
-b boot/grub/i386-pc/eltorito.img \
|
|
-no-emul-boot -boot-load-size 4 -boot-info-table \
|
|
--grub2-boot-info \
|
|
-o "$ISO" \
|
|
"$ISO_ROOT" 2>&1 | grep -viE "^xorriso : NOTE|Drive current|Media current|Media status|Media summary|libisofs:|^xorriso : UPDATE" || true
|
|
|
|
[ -s "$ISO" ] || { echo "FALLO: xorriso no produjo el ISO" >&2; exit 1; }
|
|
rm -rf "$STAGE"
|
|
echo "==> ISO live creado: $(du -h "$ISO" | cut -f1) — $ISO"
|
|
echo " auto-boot: qemu-system-x86_64 -cdrom $ISO -boot d -nographic"
|
|
|
|
if [ "${BOOT:-0}" = 1 ]; then
|
|
echo "==> arranque de prueba (desde el CD El Torito)"
|
|
accel=""
|
|
[ "${KVM:-0}" = 1 ] && [ -w /dev/kvm ] && accel="-enable-kvm -cpu host"
|
|
# shellcheck disable=SC2086
|
|
exec qemu-system-x86_64 -m "${MEM:-4096}" -no-reboot -nographic $accel \
|
|
-cdrom "$ISO" -boot d
|
|
fi
|