#!/bin/bash
# ============================================================
#  fws-secureboot-setup — prépare FWS à booter SIGNÉ sous Secure Boot,
#  SANS activer le lockdown noyau (→ hibernation préservée).
#
#  POURQUOI : Vanguard exige Secure Boot (réglage firmware GLOBAL) → FWS doit
#  lui aussi booter sous SB, sinon le firmware refuse de le lancer. Fait vérifié :
#  sur noyau mainline Arch, activer Secure Boot n'arme PAS le lockdown (le patch
#  Fedora/Ubuntu qui lie les deux a été refusé upstream). Signature (firmware) et
#  lockdown (LSM runtime) sont ORTHOGONAUX → on peut signer ET hiberner.
#
#  VOIE RETENUE : sbctl (clés « db » custom) en CONSERVANT les clés Microsoft
#  (--microsoft), pour que Windows et les OpROM continuent de booter.
#
#  ⚠ ORDRE IMPÉRATIF : tout SIGNER avant d'activer Secure Boot au firmware.
#    Détails, alternative shim+MOK et vérifications : docs §4.
# ============================================================
set -u
[ "$(id -u)" -eq 0 ] || { echo "root requis (sudo fws-secureboot-setup)"; exit 1; }
[ -d /sys/firmware/efi ] || { echo "Système non-UEFI : Secure Boot sans objet."; exit 1; }

log()  { printf '\e[36m==>\e[0m %s\n' "$*"; }
warn() { printf '\e[33m[!] %s\e[0m\n' "$*"; }
die()  { printf '\e[31m[ERREUR] %s\e[0m\n' "$*"; exit 1; }

command -v sbctl >/dev/null 2>&1 || { log "Installation de sbctl…"; pacman -S --noconfirm --needed sbctl || die "sbctl introuvable (réseau ?)"; }
command -v objdump >/dev/null 2>&1 || pacman -S --noconfirm --needed binutils || true

# Localiser l'ESP et grubx64.efi. IDENTITÉ = FWS, cohérente avec le kickstart
# install_grub (--bootloader-id=FWS + --removable → \EFI\FWS\ ET \EFI\BOOT\).
# Signer un \EFI\GRUB\ séparé ne servirait à RIEN : le firmware charge \EFI\FWS\
# (ou le secours \EFI\BOOT\BOOTX64.EFI) → ce sont EUX qu'il faut signer.
ESP_DIR=/boot/efi; [ -d "$ESP_DIR/EFI" ] || ESP_DIR=/boot
GRUB_EFI="$ESP_DIR/EFI/FWS/grubx64.efi"
[ -f "$GRUB_EFI" ] || GRUB_EFI="$(find "$ESP_DIR/EFI" -iname 'grubx64.efi' 2>/dev/null | head -1)"
[ -n "$GRUB_EFI" ] && [ -f "$GRUB_EFI" ] || die "grubx64.efi introuvable sous $ESP_DIR/EFI"
BOOTX64="$ESP_DIR/EFI/BOOT/BOOTX64.EFI"   # chemin de secours removable (à signer aussi)

# 1) GRUB doit embarquer SBAT (+ shim_lock), sinon shim refusera de le charger.
#    Un grub-install « nu » produit un binaire sans .sbat → on réinstalle EN FWS
#    (et on régénère le secours removable \EFI\BOOT\BOOTX64.EFI avec le même SBAT).
if ! command -v objdump >/dev/null 2>&1; then
    warn "objdump (binutils) absent → SBAT non vérifiable, réinstallation de GRUB SAUTÉE (on suppose GRUB déjà correct)."
elif ! objdump -h "$GRUB_EFI" 2>/dev/null | grep -q '\.sbat'; then
    [ -f /usr/share/grub/sbat.csv ] || die "sbat.csv introuvable — impossible d'ajouter SBAT"
    warn "grubx64.efi sans section .sbat → réinstallation de GRUB (--bootloader-id=FWS + --sbat)."
    GRUB_MODULES='normal search part_gpt part_msdos fat ext2 configfile linux echo test true loadenv all_video efi_gop tpm'
    grub-install --target=x86_64-efi --efi-directory="$ESP_DIR" --bootloader-id=FWS \
        --sbat /usr/share/grub/sbat.csv --modules="$GRUB_MODULES" \
        || die "grub-install (FWS) a échoué"
    grub-install --target=x86_64-efi --efi-directory="$ESP_DIR" --bootloader-id=FWS --removable \
        --sbat /usr/share/grub/sbat.csv --modules="$GRUB_MODULES" \
        || warn "grub-install --removable (secours) a échoué"
    GRUB_EFI="$ESP_DIR/EFI/FWS/grubx64.efi"
    objdump -h "$GRUB_EFI" 2>/dev/null | grep -q '\.sbat' || die "SBAT toujours absent après réinstallation"
    grub-mkconfig -o /boot/grub/grub.cfg 2>/dev/null || true
fi

# 2) Clés sbctl (idempotent).
if ! sbctl status 2>/dev/null | grep -qi 'setup mode.*✓\|setup mode.*enabled\|Setup Mode.*Enabled'; then
    warn "Firmware pas en Setup Mode : « enroll-keys » échouera. Mets le firmware en Setup Mode (efface les clés d'usine), puis relance. On continue quand même la génération/signature."
fi
[ -d /var/lib/sbctl/keys ] || sbctl create-keys || die "sbctl create-keys a échoué"

# 3) Enrôler NOS clés + CONSERVER Microsoft (sinon Windows/OpROM cassés).
log "Enrôlement des clés (avec Microsoft)…"
sbctl enroll-keys --microsoft \
    || warn "enroll-keys a échoué (firmware pas en Setup Mode ?) — à refaire une fois en Setup Mode."

# 4) Signer les TROIS chemins réellement chargés par le firmware + les noyaux :
#    \EFI\FWS\grubx64.efi, le secours \EFI\BOOT\BOOTX64.EFI, et chaque vmlinuz.
log "Signature de GRUB (FWS + secours removable) et des noyaux…"
sbctl sign -s "$GRUB_EFI" || die "signature de $GRUB_EFI échouée"
[ -f "$BOOTX64" ] && { sbctl sign -s "$BOOTX64" || warn "signature de $BOOTX64 échouée"; }
for k in /boot/vmlinuz-linux /boot/vmlinuz-linux-lts /boot/vmlinuz-linux-zen /boot/vmlinuz-linux-hardened; do
    [ -f "$k" ] && { sbctl sign -s "$k" || warn "signature de $k échouée"; }
done
sbctl verify || warn "sbctl verify signale des binaires non signés (voir ci-dessus)."

cat <<'EOF'

=== Étapes MANUELLES restantes (firmware) ===
  1. Redémarre dans le setup du firmware (UEFI/BIOS).
  2. Active Secure Boot (les clés viennent d'être enrôlées, Microsoft conservé).
  3. Au boot FWS suivant, vérifie :
       bootctl status | grep 'Secure Boot'     →  Secure Boot: enabled
       cat /sys/kernel/security/lockdown        →  [none]   (hibernation OK)
       cat /sys/power/state                     →  contient « disk »
     Puis :  fws-gameboot doctor

Re-signature AUTOMATIQUE après chaque MAJ noyau/GRUB via le hook pacman
/usr/share/libalpm/hooks/95-fws-secureboot-sign.hook (+ le hook natif de sbctl).
EOF
