#!/bin/sh # disk-image.sh — Etapa B (imagen en disco real): empaqueta un rootfs como imagen ext4 booteable de # disco virtio (/dev/vda) en vez de initramfs. Con un kernel que trae VIRTIO_BLK+EXT4 built-in # (recipes/linux.toml), QEMU monta la imagen como root REAL y el kernel arranca con # `root=/dev/vda rw rdinit=/sbin/init` — sin initramfs, sin el wrapper /init+switch_root: `/` ya es un # mount ext4 pivotable (el muro pivot_root del path initramfs desaparece por construcción). # # `mke2fs -d ` puebla la imagen DESDE un directorio sin montar nada y sin root (e2fsprogs >= 1.43). # # Uso: # ./scripts/disk-image.sh # crea work/hammer-disk.img desde work/builder-rootfs # BOOT=1 KERNEL= KVM=1 ./scripts/disk-image.sh # además bootea y corre rebuild-stage1 # # Variables: # ROOTFS dir rootfs a empaquetar (default work/builder-rootfs, lo arma selfhost-verify) # IMG imagen de salida (default work/hammer-disk.img) # SIZE tamaño de la imagen (default 6G; el rootfs ronda ~2G + holgura para el rebuild) # BOOT 1 ⇒ bootea con drive-rebuild.py tras crear la imagen # KERNEL bzImage con VIRTIO_BLK+EXT4 (requerido si BOOT=1) # KVM/MEM/NET passthrough a drive-rebuild.py set -eu ROOT="$(cd "$(dirname "$0")/.." && pwd)" cd "$ROOT" ROOTFS="${ROOTFS:-work/builder-rootfs}" IMG="${IMG:-work/hammer-disk.img}" SIZE="${SIZE:-6G}" [ -d "$ROOTFS" ] || { echo "no existe ROOTFS: $ROOTFS (corré selfhost-verify para armar el builder)" >&2; exit 1; } [ -x "$ROOTFS/sbin/init" ] || [ -L "$ROOTFS/sbin/init" ] || { echo "ROOTFS sin /sbin/init (arje-zero)" >&2; exit 1; } echo "==> rootfs : $ROOTFS ($(du -sh "$ROOTFS" | cut -f1))" echo "==> imagen : $IMG ($SIZE, ext4, label hammer-root)" rm -f "$IMG" # Ownership root en la imagen (igual que el `--owner=root:root` del cpio): el rebuild usa bwrap+overlay # con un userns que mapea 0→0; si los ficheros van con el uid del host (1000) el copy-up falla EACCES. # `unshare -r` mapea nuestro uid→0, así los ficheros uid-1000 se ven como root y mke2fs escribe uid 0 # en la imagen — sin sudo. mke2fs -d puebla desde el dir sin montar. Fallback a mke2fs directo si no hay # unshare (la imagen quedaría uid-host: bootea y da shell, pero el rebuild fallaría en el copy-up). if command -v unshare >/dev/null 2>&1 && unshare -r true 2>/dev/null; then unshare -r mke2fs -q -t ext4 -L hammer-root -d "$ROOTFS" "$IMG" "$SIZE" else echo " (sin unshare -r: imagen con uid del host; el rebuild in-VM podría fallar el copy-up)" >&2 mke2fs -q -t ext4 -L hammer-root -d "$ROOTFS" "$IMG" "$SIZE" fi echo "==> imagen creada: $(du -h "$IMG" | cut -f1)" if [ "${BOOT:-0}" = 1 ]; then [ -n "${KERNEL:-}" ] || { echo "BOOT=1 requiere KERNEL=" >&2; exit 1; } echo "==> booteando de disco (root=/dev/vda, sin initramfs ni switch_root)" DISK="$IMG" KERNEL="$KERNEL" KVM="${KVM:-0}" MEM="${MEM:-6144}" NET="${NET:-1}" \ python3 scripts/drive-rebuild.py fi