Etapa metal: arranque UEFI por EFI-stub directo (esquiva GRUB 2.14 roto)

La rama GRUB-EFI cuelga (bug GRUB 2.14 del host rolling, afecta a cualquier kernel).
Solución: bootear el kernel por su EFI-STUB directo, sin GRUB-EFI.

- linux-metal.toml: CONFIG_CMDLINE_BOOL=y + CMDLINE horneado
  ('console=tty0 ... initrd=/initramfs.cpio.gz rdinit=/init'). Sin FORCE ⇒ en BIOS
  GRUB sigue mandando su cmdline. Confirmado en fuente (libstub/file.c:50): el
  EFI-stub convierte '/'→'\' y efi_load_initrd cae a la carga por cmdline sin loader.
- iso-image.sh: modo EFI_STUB=1 ⇒ la ESP lleva el bzImage como \EFI\BOOT\BOOTX64.EFI
  + initramfs.cpio.gz en su raíz (FAT32). La firmware lanza el kernel directo.
- metal-iso.sh: pasa EFI=1 EFI_STUB=1 (híbrido: BIOS GRUB + UEFI EFI-stub).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-22 21:57:46 -04:00
co-authored by Claude Opus 4.8
parent 487d741f08
commit b1e2eb95ce
3 changed files with 45 additions and 20 deletions
+31 -16
View File
@@ -138,27 +138,42 @@ grub-mkimage -O i386-pc-eltorito -p '/boot/grub' -o "$ISO_ROOT/boot/grub/i386-pc
# EFI_STUB; aquí GRUB EFI es el cargador (espeja la rama BIOS). xorriso añade un 2º El Torito (EFI). ---
EFI_ARGS=""
if [ "${EFI:-0}" = 1 ]; then
[ -d "$GRUB_EFI_LIB" ] || { echo "faltan módulos GRUB x86_64-efi en $GRUB_EFI_LIB" >&2; exit 1; }
MFORMAT="$MTOOLS_DIR/mformat"; MCOPY="$MTOOLS_DIR/mcopy"; MMD="$MTOOLS_DIR/mmd"
[ -x "$MFORMAT" ] && [ -x "$MCOPY" ] || MFORMAT="$(command -v mformat 2>/dev/null || true)"
[ -n "$MFORMAT" ] && [ -x "$MFORMAT" ] || { echo "no encuentro mtools (build recipes/mtools.toml)" >&2; exit 1; }
[ -x "$MCOPY" ] || { MCOPY="$(command -v mcopy)"; MMD="$(command -v mmd)"; }
echo "==> EFI=1: grub-mkimage x86_64-efi + ESP FAT (mtools: $MFORMAT)"
mkdir -p "$STAGE/efi"
grub-mkimage -O x86_64-efi -p '/boot/grub' -o "$STAGE/efi/bootx64.efi" \
part_gpt part_msdos fat iso9660 normal configfile linux echo ls boot search search_fs_uuid efi_gop efi_uga
# ESP FAT: dimensionada al grubx64.efi (+ holgura). mformat sobre una imagen truncada (FAT sin
# particionar; el El Torito EFI arranca el FS plano). Poblamos EFI/BOOT/BOOTX64.EFI con mcopy.
ESP="$ISO_ROOT/boot/grub/efi.img"
# Tamaño ≥ 1.44 MiB (mínimo razonable); mformat SIN -F auto-elige FAT12/16 por nº de clusters. NO
# forzar FAT32 (-F): exige ~33 MiB mínimos y sobre una imagen chica deja un FAT inválido que la
# firmware no lee ("failed to load ... Not Found").
espkb=$(( ( $(stat -c%s "$STAGE/efi/bootx64.efi") / 1024 ) + 512 ))
[ "$espkb" -lt 1440 ] && espkb=1440
rm -f "$ESP"; truncate -s "$(( espkb * 1024 ))" "$ESP"
"$MFORMAT" -i "$ESP" ::
"$MMD" -i "$ESP" ::/EFI ::/EFI/BOOT
"$MCOPY" -i "$ESP" "$STAGE/efi/bootx64.efi" ::/EFI/BOOT/BOOTX64.EFI
if [ "${EFI_STUB:-0}" = 1 ]; then
# --- EFI_STUB=1: arranque por EFI-STUB DIRECTO (sin GRUB-EFI). El bzImage ES el BOOTX64.EFI; la
# firmware lo lanza por el path de medio removible \EFI\BOOT\BOOTX64.EFI. El cmdline va
# HORNEADO en el kernel (CONFIG_CMDLINE, recipes/linux-metal.toml) con initrd=/initramfs.cpio.gz
# ⇒ el EFI-stub carga el initrd de la PROPIA ESP (file.c convierte '/'→'\'). Esquiva el bug de
# GRUB 2.14 que cuelga la rama UEFI con cualquier kernel. ---
INITRAMFS="$ISO_ROOT/boot/initramfs.cpio.gz"
[ -r "$INITRAMFS" ] || { echo "no encuentro $INITRAMFS para la ESP EFI-stub" >&2; exit 1; }
echo "==> EFI=1 EFI_STUB=1: kernel→BOOTX64.EFI + initramfs en la ESP (FAT32, sin GRUB-EFI)"
# ESP grande (kernel + initramfs + holgura) ⇒ FAT32 (-F), válido y recomendado para ESP en metal.
espkb=$(( ( $(stat -c%s "$KERNEL") + $(stat -c%s "$INITRAMFS") ) / 1024 + 8192 ))
rm -f "$ESP"; truncate -s "$(( espkb * 1024 ))" "$ESP"
"$MFORMAT" -F -i "$ESP" ::
"$MMD" -i "$ESP" ::/EFI ::/EFI/BOOT
"$MCOPY" -i "$ESP" "$KERNEL" ::/EFI/BOOT/BOOTX64.EFI
"$MCOPY" -i "$ESP" "$INITRAMFS" ::/initramfs.cpio.gz
else
# --- EFI=1 (default): GRUB EFI como cargador (espeja la rama BIOS, lee kernel+initrd del iso9660). ---
[ -d "$GRUB_EFI_LIB" ] || { echo "faltan módulos GRUB x86_64-efi en $GRUB_EFI_LIB" >&2; exit 1; }
echo "==> EFI=1: grub-mkimage x86_64-efi + ESP FAT (mtools: $MFORMAT)"
mkdir -p "$STAGE/efi"
grub-mkimage -O x86_64-efi -p '/boot/grub' -o "$STAGE/efi/bootx64.efi" \
part_gpt part_msdos fat iso9660 normal configfile linux echo ls boot search search_fs_uuid efi_gop efi_uga
# Tamaño ≥ 1.44 MiB; mformat SIN -F auto-elige FAT12/16 por nº de clusters (FAT32 exige ~33 MiB).
espkb=$(( ( $(stat -c%s "$STAGE/efi/bootx64.efi") / 1024 ) + 512 ))
[ "$espkb" -lt 1440 ] && espkb=1440
rm -f "$ESP"; truncate -s "$(( espkb * 1024 ))" "$ESP"
"$MFORMAT" -i "$ESP" ::
"$MMD" -i "$ESP" ::/EFI ::/EFI/BOOT
"$MCOPY" -i "$ESP" "$STAGE/efi/bootx64.efi" ::/EFI/BOOT/BOOTX64.EFI
fi
EFI_ARGS="-eltorito-alt-boot -e boot/grub/efi.img -no-emul-boot -isohybrid-gpt-basdat"
fi