Files
takana/scripts/metal-usb-sdboot.sh
T
sergioandClaude Opus 4.8 5012549f85 Etapa metal: USB de bisección (initramfs tiny) + fix piso FAT32 de la ESP
- Diagnóstico metal: con systemd-boot, earlyprintk=efi NO imprime NADA del kernel
  (solo 'Loaded initrd MEDIA_GUID' + 'Measured initrd PCR 9' y cuelga) ⇒ el kernel
  no llega ni a su consola temprana: hang en ExitBootServices o el decompresor.
- metal-usb-sdboot.sh: piso de 48MiB a la ESP (FAT32 -F exige ~33MiB; con initramfs
  chico caía debajo y la firmware no leía el BOOTX64.EFI → 'Not Found').
- USB de bisección (work/hammer-tiny-usb.img, initramfs busybox 1.3MB): ✓ OVMF llega a
  /init. Si en el metal del usuario ARRANCA a shell ⇒ el cuelgue era el initrd 100MB;
  si TAMBIÉN cuelga ⇒ es el kernel/EBS (probar nokaslr/no5lvl).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 01:26:29 -04:00

86 lines
5.0 KiB
Bash
Executable File

#!/usr/bin/env sh
# metal-usb-sdboot.sh — USB raw (GPT + ESP FAT32) que arranca hammer en metal vía systemd-boot.
#
# Alternativa de BRINGUP al boot por EFI-stub directo (que en el firmware del usuario se cuelga tras
# 'Measured initrd PCR 9', por el quirk de LoadOptions del firmware). systemd-boot:
# - pasa una cmdline LIMPIA al kernel (esquiva el quirk EFI_LOAD_OPTION del firmware),
# - provee el initrd por LoadFile2 (sin depender del initrd= de la cmdline),
# - permite EDITAR la cmdline en vivo (tecla 'e' en el menú) ⇒ iterar sin recompilar.
#
# ⚠️ systemd-bootx64.efi es un BINARIO AJENO (del host) — crutch de bringup. TODO: loader soberano.
#
# Salida: una IMAGEN DE DISCO (no ISO) para dd directo al pendrive:
# sudo dd if=work/hammer-metal-usb.img of=/dev/sdX bs=4M oflag=sync status=progress
#
# Uso: scripts/metal-usb-sdboot.sh
# Vars: ROOTFS (def work/metal-rootfs) KERNEL (def store/*-linux-metal más reciente)
# SDBOOT (def systemd-bootx64.efi del host) IMG (def work/hammer-metal-usb.img)
# OPTIONS (cmdline del loader entry)
set -eu
ROOT="$(cd "$(dirname "$0")/.." && pwd)"; cd "$ROOT"
ROOTFS="${ROOTFS:-work/metal-rootfs}"
[ -d "$ROOTFS" ] || { echo "no existe ROOTFS=$ROOTFS (corré scripts/metal-iso.sh primero)" >&2; exit 1; }
KERNEL="${KERNEL:-$(ls -dt store/*-linux-metal/boot/bzImage 2>/dev/null | head -1)}"
[ -n "${KERNEL:-}" ] && [ -r "$KERNEL" ] || { echo "no encuentro kernel metal" >&2; exit 1; }
SDBOOT="${SDBOOT:-/home/sergio/.local/share/shuma/rootfs/arch/usr/lib/systemd/boot/efi/systemd-bootx64.efi}"
[ -r "$SDBOOT" ] || { echo "no encuentro systemd-bootx64.efi en $SDBOOT" >&2; exit 1; }
MT=$(ls -d store/*-mtools/usr/bin 2>/dev/null | head -1)
[ -n "$MT" ] && [ -x "$MT/mformat" ] || { echo "no encuentro mtools de hammer (build recipes/mtools.toml)" >&2; exit 1; }
IMG="${IMG:-work/hammer-metal-usb.img}"
# /dev/console=tty0 al FINAL ⇒ la getty de arje da shell en la PANTALLA. earlyprintk=efi para diagnóstico.
OPTIONS="${OPTIONS:-earlyprintk=efi,keep ignore_loglevel efi=novamap console=ttyS0,115200 console=tty0}"
WORK="$ROOT/work/metal-sdboot"; rm -rf "$WORK"; mkdir -p "$WORK"
echo "==> kernel: $KERNEL"
echo "==> rootfs: $ROOTFS ($(du -sh "$ROOTFS" | cut -f1))"
# 1) staging del initramfs: hardlinks del rootfs + /init del medio live (rdinit=/init lo corre)
echo "==> staging initramfs (+ /init marcador live)"
STG="$WORK/rfs"; cp -al "$ROOTFS" "$STG"
cat > "$STG/init" <<'INIT'
#!/bin/sh
/bin/busybox mount -t proc proc /proc 2>/dev/null || true
/bin/busybox mount -t sysfs sys /sys 2>/dev/null || true
/bin/busybox mount -t devtmpfs dev /dev 2>/dev/null || true
echo "HAMMER-METAL-LIVE-OK: arranque por systemd-boot"
exec /sbin/init
INIT
chmod +x "$STG/init"
# 2) empaquetar initramfs.cpio.gz (root-owned, igual que iso-image.sh)
echo "==> empaquetando initramfs.cpio.gz"
( cd "$STG" && find . -print0 | cpio --null -o -H newc -R 0:0 2>/dev/null | gzip -1 ) > "$WORK/initramfs.cpio.gz"
IRD="$WORK/initramfs.cpio.gz"; echo " initramfs: $(du -h "$IRD" | cut -f1)"
# 3) ESP FAT32: BOOTX64.EFI=systemd-boot + loader.conf + entry + kernel + initrd
espkb=$(( ( $(stat -c%s "$KERNEL") + $(stat -c%s "$IRD") ) / 1024 + 16384 ))
# FAT32 (-F) exige ~33 MiB mínimos; con initramfs chico (bisección) la ESP cae por debajo y la firmware
# no la lee ("Not Found"). Piso de 48 MiB para que el FAT32 siempre sea válido.
[ "$espkb" -lt 49152 ] && espkb=49152
ESP="$WORK/esp.img"; rm -f "$ESP"; truncate -s "$(( espkb * 1024 ))" "$ESP"
"$MT/mformat" -F -v HAMMER -i "$ESP" ::
"$MT/mmd" -i "$ESP" ::/EFI ::/EFI/BOOT ::/loader ::/loader/entries
"$MT/mcopy" -i "$ESP" "$SDBOOT" ::/EFI/BOOT/BOOTX64.EFI
printf 'default hammer\ntimeout 8\neditor yes\n' > "$WORK/loader.conf"
printf 'title hammer (metal)\nlinux /bzImage\ninitrd /initramfs.cpio.gz\noptions %s\n' "$OPTIONS" > "$WORK/hammer.conf"
"$MT/mcopy" -i "$ESP" "$WORK/loader.conf" ::/loader/loader.conf
"$MT/mcopy" -i "$ESP" "$WORK/hammer.conf" ::/loader/entries/hammer.conf
"$MT/mcopy" -i "$ESP" "$KERNEL" ::/bzImage
"$MT/mcopy" -i "$ESP" "$IRD" ::/initramfs.cpio.gz
echo "==> ESP poblada ($(du -h "$ESP" | cut -f1)):"
"$MT/mdir" -i "$ESP" ::/ ::/EFI/BOOT ::/loader/entries 2>/dev/null | grep -iE 'BOOTX64|bzImage|initram|hammer|loader' || true
# 4) imagen de disco GPT: GPT primaria (1MiB) + ESP (en sector 2048) + GPT backup
esp_sectors=$(( espkb * 2 )) # KiB→sectores de 512
rm -f "$IMG"; truncate -s "$(( (2048 + esp_sectors + 2048) * 512 ))" "$IMG"
echo "label: gpt
start=2048, size=$esp_sectors, type=C12A7328-F81F-11D2-BA4B-00A0C93EC93B, name=\"EFI System Partition\"" | sfdisk --quiet "$IMG"
dd if="$ESP" of="$IMG" bs=512 seek=2048 conv=notrunc status=none
echo
echo "✓ USB metal (systemd-boot): $IMG ($(du -h "$IMG" | cut -f1))"
echo " Quemar: sudo dd if=$IMG of=/dev/sdX bs=4M oflag=sync status=progress"
echo " Bootear: el menú de systemd-boot aparece; ENTER arranca. Tecla 'e' = EDITAR la cmdline en vivo."
echo " Secure Boot OFF. WiFi (en consola): wifi-connect \"SSID\" \"CLAVE\""