diff --git a/scripts/efi-disk-boot-test.sh b/scripts/efi-disk-boot-test.sh new file mode 100755 index 00000000..bf592fd9 --- /dev/null +++ b/scripts/efi-disk-boot-test.sh @@ -0,0 +1,50 @@ +#!/usr/bin/env bash +# efi-disk-boot-test.sh — valida el DISCO INSTALADO EFI-STUB soberano (ADR 0010 paso 5) en OVMF. +# +# Arma la imagen con install-image-efi.sh y la arranca por UEFI (OVMF pflash, SIN -kernel: la firmware +# lanza \EFI\BOOT\BOOTX64.EFI). Asevera la cadena soberana completa por marcadores serie deterministas: +# 1. EFI-stub cargó el kernel+initrd horneados (sin GRUB ni systemd-boot) +# 2. el initramfs de pivote resolvió hammer-root por LABEL y montó las ext4 +# 3. switch_root: arje-zero re-montó / (re-mounted) = tomó PID1 +# +# Nota: el cmdline horneado termina en console=tty0 ⇒ el stdout de userspace va a la pantalla. Los +# marcadores kernel-side (printk a TODAS las consolas) más el tee a /dev/ttyS0 del /init dan la prueba +# en el serial headless. +# +# Uso: ./scripts/efi-disk-boot-test.sh +# Vars: ROOTFS KERNEL MEM (def 4096) KVM (def 1) DEADLINE (def 180) OVMF_CODE OVMF_VARS +set -euo pipefail +ROOT="$(cd "$(dirname "$0")/.." && pwd)"; cd "$ROOT" +MEM="${MEM:-4096}"; KVM="${KVM:-1}"; DEADLINE="${DEADLINE:-180}" +WORK="$ROOT/work/efi-disk-boot-test"; mkdir -p "$WORK" +IMG="$WORK/hammer-efi-disk.img"; LOG="$WORK/boot.log" + +echo "==> armando la imagen EFI-stub con install-image-efi.sh" +IMG="$IMG" ROOTFS="${ROOTFS:-}" KERNEL="${KERNEL:-}" ./scripts/install-image-efi.sh >"$WORK/build.log" 2>&1 \ + || { echo "✗ build falló — ver $WORK/build.log" >&2; tail -20 "$WORK/build.log" >&2; exit 1; } +echo " imagen: $(du -h "$IMG" | cut -f1)" + +echo "==> arranque UEFI (OVMF, sin -kernel) — deadline ${DEADLINE}s" +BOOT=1 KVM="$KVM" MEM="$MEM" DEADLINE="$DEADLINE" IMG="$IMG" \ + ./scripts/install-image-efi.sh >"$LOG" 2>&1 || true + +# marcadores (limpiamos escapes ANSI que mete OVMF) +clean() { sed 's/\x1b\[[0-9;]*[a-zA-Z]//g; s/\r//g' "$LOG"; } +fail=0 +# Los dos primeros bytes serie del handoff firmware→kernel se pierden a veces (EFI-stub/Linux-version): +# son INFORMATIVOS. El veredicto se apoya en los marcadores AGUAS ABAJO — prueba concluyente de que +# EFI-stub cargó el kernel+initrd (nada más podría montar hammer-root ni re-montar / sin esta cadena). +info() { if clean | grep -aqiE "$1"; then echo " · $2"; else echo " · ($2 — bytes serie tempranos perdidos, no bloqueante)"; fi; } +check() { if clean | grep -aqiE "$1"; then echo " ✓ $2"; else echo " ✗ $2 (falta /$1/)"; fail=1; fi; } +info 'EFI stub: Loaded initrd' 'EFI-stub cargó kernel+initrd (sin GRUB/systemd-boot)' +info 'Linux version 6\.16' 'kernel arrancó' +check 'HAMMER-EFI-DISK-PIVOT-OK|EXT4-fs \(vda2\): mounted' 'initramfs pivote montó hammer-root (⇒ EFI-stub cargó kernel+initrd)' +check 'EXT4-fs \(vda3\): mounted' '/store montado por LABEL' +check 'EXT4-fs \(vda2\): re-mounted' 'switch_root → arje-zero re-montó / (PID1)' + +echo +if [ "$fail" = 0 ]; then + echo "✓✓ EFI-DISK VERDE: disco instalado bootea EFI-stub SOBERANO en OVMF (firmware → BOOTX64.EFI → pivote → arje-zero)" +else + echo "✗ efi-disk-boot-test FALLÓ — log: $LOG" >&2; exit 1 +fi diff --git a/scripts/install-image-efi.sh b/scripts/install-image-efi.sh new file mode 100755 index 00000000..a8653cd7 --- /dev/null +++ b/scripts/install-image-efi.sh @@ -0,0 +1,183 @@ +#!/bin/sh +# install-image-efi.sh — imagen de disco EFI-STUB SOBERANA (ADR 0010 paso 5), validable en OVMF. +# +# Hermana EFI de scripts/install-image.sh (que es GPT+BIOS+GRUB). Ésta NO lleva GRUB ni systemd-boot: +# el propio bzImage es el binario EFI (EFI-STUB) que la firmware lanza como \EFI\BOOT\BOOTX64.EFI (la +# ruta de arranque FALLBACK de medios removibles, sin necesidad de una entrada NVRAM). Es el loader +# soberano del ADR 0010: sin bootloader ajeno, sin el GRUB 2.14 que cuelga la rama UEFI en el metal. +# +# Cómo pasa el cmdline sin LoadOptions: el kernel `linux-metal` hornea CONFIG_CMDLINE (CMDLINE_BOOL, sin +# FORCE) = "... initrd=/initramfs.cpio.gz rdinit=/init". Arrancado por la ruta fallback la firmware pasa +# LoadOptions VACÍO ⇒ el kernel usa ese cmdline horneado ⇒ el EFI-stub carga \initramfs.cpio.gz desde la +# MISMA ESP y corre /init. (En un boot con bootloader que sí pasa LoadOptions, el horneado se ignora.) +# +# El initramfs es MÍNIMO — sólo pivota: findfs LABEL=hammer-root → switch_root a la ext4 real. Ese +# "initrd chico" es lo que destraba EFI-stub directo (ADR 0010 paso 2: el cuelgue del metal era por un +# initrd de 100MB). El sistema real vive en las particiones ext4, no en RAM. +# +# Layout (GPT, UEFI): +# p1 ESP FAT32 [EFI System Partition] \EFI\BOOT\BOOTX64.EFI (=bzImage) + \initramfs.cpio.gz +# p2 / ext4 [hammer-root] el rootfs real del producto (/sbin/init → arje-zero) +# p3 /store ext4 [hammer-store] +# p4 /var/lib/hammer ext4 [hammer-state] +# +# Cadena de arranque del disco: firmware UEFI → \EFI\BOOT\BOOTX64.EFI (EFI-stub) → initramfs pivote +# (findfs LABEL=hammer-root → switch_root) → /sbin/init real → arje-zero PID1. +# +# La ESP se puebla con el mtools de hammer (mformat/mcopy, sin root ni loop). Las ext4 con `mke2fs -d` +# bajo `unshare -r` (ficheros root-owned sin sudo), igual que install-image.sh. +# +# Uso: +# ./scripts/install-image-efi.sh # crea work/hammer-efi-disk.img +# BOOT=1 KVM=1 ./scripts/install-image-efi.sh # además lo arranca en OVMF (sin -kernel) +# +# Variables: +# ROOTFS dir rootfs a instalar (default el product-rootfs más reciente del store) +# KERNEL bzImage EFI-stub a embeber (default store/*-linux-metal/boot/bzImage más reciente) +# BUSYBOX busybox ESTÁTICO para el initramfs (default el del ROOTFS) +# MTOOLS dir usr/bin de mtools de hammer (default store/*-mtools/usr/bin) +# IMG imagen de salida (default work/hammer-efi-disk.img) +# ESP_MB MiB de la ESP FAT32 (default 64) +# ROOT_SIZE MiB de / (default 2048) +# STORE_SIZE MiB de /store (default 512) +# STATE_SIZE MiB de /var/lib/hammer (default 512) +# BOOT 1 ⇒ arranca en OVMF tras crearla KVM/MEM passthrough al arranque +# OVMF_CODE/OVMF_VARS firmware OVMF (default Arch/CachyOS) +set -eu +ROOT="$(cd "$(dirname "$0")/.." && pwd)" +cd "$ROOT" + +ROOTFS="${ROOTFS:-$(ls -dt store/*-product-rootfs 2>/dev/null | head -1)}" +KERNEL="${KERNEL:-$(ls -dt store/*-linux-metal/boot/bzImage 2>/dev/null | head -1)}" +IMG="${IMG:-work/hammer-efi-disk.img}" +ESP_MB="${ESP_MB:-64}" +ROOT_SIZE="${ROOT_SIZE:-2048}" +STORE_SIZE="${STORE_SIZE:-512}" +STATE_SIZE="${STATE_SIZE:-512}" +MTOOLS="${MTOOLS:-$(ls -dt store/*-mtools/usr/bin 2>/dev/null | head -1)}" + +[ -n "${ROOTFS:-}" ] && [ -d "$ROOTFS" ] || { echo "no existe ROOTFS: '${ROOTFS:-}' (set ROOTFS=