Files
FWS-ISO/docs/hibernate-swap-dualboot.md
nocode e811cce88d docs(hibernate-swap-dualboot): update windows version references from 24H2 to 25H2
Update documentation to reflect Windows 11 25H2 as the current default version in three locations:
- Initial requirements section
- BitLocker risk mitigation (row 5)
- VBS/Hyper-V validation note (row 11)

These changes align the documentation with the latest Windows 11 release cycle.
2026-07-08 23:56:29 +02:00

20 KiB
Raw Permalink Blame History

Plan de build — FWS « HibernateSwap DualBoot » (Valorant/Vanguard)

Document de build final. Le design est validé et acquis : ce plan le rend buildable, intègre les corrections bloquantes de la revue adversariale et fixe l'ordre d'exécution. Cible réelle : UEFI, Zen 5, 60,45 GiB RAM, 3× NVMe 2 To (Samsung 990 PRO), RTX 5090 Blackwell (pilote propriétaire 610.43.02), TPM 2.0, GRUB, noyau 7.1.2arch31, Secure Boot OFF, aucun swap.


1. Résumé & principe

L'utilisateur clique « Jouer à Valorant » dans FWS. FWS hiberne (RAM → swap disque) après avoir armé un boot oneshot UEFI (BootNext) vers un Windows 11 baremetal installé sur une partition NTFS dédiée. Le firmware lance Windows directement (\EFI\Microsoft\Boot\bootmgfw.efi, jamais via GRUB) : Vanguard voit un vrai Windows natif. À la fermeture ou au crash de Valorant, Windows arme BootNext=FWS et reboote, le noyau voit resume= et reprend la session FWS intacte. C'est un dualboot baremetal des deux côtés — configuration que Vanguard tolère — avec BootOrder[0]=FWS comme filet de sûreté permanent.


2. Prérequis matériels / logiciels

Matériel (vérifié sur cible)

  • UEFI en User Mode (SetupMode=0), db d'usine Microsoft présents, TPM 2.0, IOMMU activable au firmware (à confirmer dans le setup).
  • 3× NVMe entièrement partitionnés, zéro espace non alloué (à reconfirmer via parted … print free).
  • GPU RTX 5090 : facteur critique d'hibernation (VRAM 32 Go) — voir §7.

Logiciels côté FWS (Arch)

  • Paquets à ajouter : sbsigntools / sbctl, efibootmgr, mokutil, wimlib, ntfs-3g, polkit, python-gobject, gtk3, nvidia/nvidia-utils + nvidia-hibernate/nvidia-resume (hooks S4 NVIDIA).
  • Interdits (casseraient l'hibernation) : linux-hardened, patch autolockdown Fedora, lockdown= en cmdline, initramfs systemd non planifié.
  • Invariants à figer en CI : /sys/kernel/security/lockdown == [none], /sys/power/state contient disk, cmdline sans lockdown=.

Côté Windows (fourni par l'utilisateur, non bundlé)

  • ISO Windows 11 légitime, TPM 2.0 + Secure Boot exigés par Riot, VBS/HVCI actifs (défaut 25H2).

3. Roadmap par phases

Phase 0 — Recon disque + firmware (root requis, BLOQUANT avant toute écriture)

for d in /dev/nvme0n1 /dev/nvme1n1 /dev/nvme2n1; do sudo parted "$d" unit MiB print free; sudo sgdisk -p "$d"; done
sudo lsblk -dpno NAME,SIZE,MODEL

Confirmer l'absence réelle d'espace libre → détermine chemin neuf (Anaconda) vs shrink postinstall. Dans le firmware : vérifier IOMMU (VTd/AMDVi) actif et BIOS à jour (exigence Vanguard).

Phase 1 — Provisionner l'hibernation (chemin machine réelle : swapfile)

Sizing RAM + VRAM + marge = 96 GiB (et non 64 : la VRAM préservée est recopiée dans l'image — voir §7).

sudo mkswap -U clear --size 96G --file /swapfile
sudo chmod 600 /swapfile
sudo swapon /swapfile && swapon --show
# fstab : ajouter '/swapfile none swap defaults 0 0' ; supprimer la ligne /mnt/games2 dupliquée
N=$(sudo filefrag -v /swapfile | awk '$1=="0:"{print substr($4,1,length($4)-2)}')   # resume_offset
sudo chattr +i /swapfile   # fige l'offset (anti-dérive silencieuse)

UUID de reprise = FS hôte (racine) 84888eb3-cab9-407b-b407-ea4b3133c4a6, pas l'UUID interne du swap.

Phase 2 — Hook resume + cmdline

# /etc/mkinitcpio.conf : resume APRÈS block, AVANT filesystems (busybox, PAS systemd)
# HOOKS=(base udev autodetect keyboard keymap modconf block resume filesystems fsck)
sudo mkinitcpio -P
sudo lsinitcpio /boot/initramfs-linux.img | grep -i resume   # doit matcher
# /etc/default/grub :
# GRUB_CMDLINE_LINUX_DEFAULT="loglevel=3 quiet resume=UUID=84888eb3-cab9-407b-b407-ea4b3133c4a6 resume_offset=N hibernate.compressor=lz4"
#   → hibernate.compressor=lz4 : compression la plus RAPIDE de l'image (moins de
#     CPU que lzo) → hibernate/resume plus courts sur une image de 60-90 Go.
# GRUB_DISABLE_OS_PROBER=true   (aucune entrée GRUB->Windows -> PCR4/PCR7 propres)
# GRUB_TIMEOUT=1  +  GRUB_TIMEOUT_STYLE=hidden  → resume quasi immédiat (menu
#   masqué, maintenir Maj/Échap pour l'afficher). Boot le plus rapide côté FWS.
sudo grub-mkconfig -o /boot/grub/grub.cfg

Phase 3 — GPU NVIDIA (sans quoi le resume graphique est cassé)

# /etc/modprobe.d/nvidia-hibernate.conf
# options nvidia NVreg_PreserveVideoMemoryAllocations=1 NVreg_TemporaryFilePath=/var/tmp
sudo systemctl enable nvidia-suspend.service nvidia-hibernate.service nvidia-resume.service

Phase 4 — Valider l'hibernation AVANT de la câbler au bouton « Jouer »

sync; echo test_resume | sudo tee /sys/power/disk; sudo systemctl hibernate   # non destructif
echo platform | sudo tee /sys/power/disk
# Puis cycle réel, SESSION GRAPHIQUE CHARGÉE (jeu/desktop lourd) :
sudo systemctl hibernate   # rallumer
journalctl -b -1 -k | grep -iE 'PM: hibernation|Image saved|resume|Restarting tasks'

Critère de succès : session préservée et affichage NVIDIA intact au resume. Échec → le flux « Jouer » doit basculer en reboot propre (§7).

Phase 5 — Secure Boot signé, lockdown OFF (§4)

Phase 6 — Installateur : carve NTFS + outillage Windows (§6)

Phase 7 — Orchestrateur oneshot + GUI (§5)

Phase 8 — Spike endtoend sur ISO réelle : hibernate → BootNext → Windows → Valorant → retour FWS.


4. Point dur Secure Boot ↔ hibernation — SOLUTION RETENUE

Le nœud : Vanguard exige Secure Boot globalement au firmware → FWS doit aussi booter sous SB. Or Fedora/Ubuntu bloquent l'hibernation sous SB via le lockdown.

Fait établi et vérifié : sur noyau mainline Arch, activer Secure Boot n'arme PAS le lockdown. Le patch Garrett/Howells liant SB↔lockdown a été refusé upstream ; il est downstream Fedora/Ubuntu uniquement. Sur la cible : CONFIG_LOCK_DOWN_IN_EFI_SECURE_BOOT absent, CONFIG_LOCK_DOWN_KERNEL_FORCE_NONE=y, pas de LSM_EARLY, /sys/kernel/security/lockdown = [none]. Signer ≠ lockdown : ils sont orthogonaux.

Solution retenue : sbctl (clés db custom), en CONSERVANT les clés Microsoft. Justification : firmware déjà en User Mode avec db Microsoft → Windows boote sans y toucher ; friction minimale ; hook pacman de resignature intégré. On garde GRUB (pas d'UKI) : cmdline resume= éditable et PCR4 firmware stable à chaque MAJ noyau (favorable à un futur scellement TPM du swap LUKS). Voie alternative documentée : shim+MOK (modèle Ubuntu/Fedora, plus robuste sur OEM verrouillés, au prix d'un prompt MokManager) — à retenir si le firmware refuse l'enrôlement db custom.

sudo pacman -S sbctl
# PRÉREQUIS NON NÉGOCIABLE : le grubx64.efi installé n'a NI .sbat NI shim_lock -> réinstaller GRUB d'abord :
sudo grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=GRUB \
  --sbat /usr/share/grub/sbat.csv --modules='normal search part_gpt part_msdos fat ext2 configfile linux echo test true loadenv all_video efi_gop tpm'
objdump -h /boot/EFI/GRUB/grubx64.efi | grep -E 'sbat'   # doit exister
# Setup Mode au firmware, puis :
sudo sbctl create-keys
sudo sbctl enroll-keys --microsoft        # IMPÉRATIF : réinjecte MS -> Windows/OROM bootent
sudo sbctl sign -s /boot/EFI/GRUB/grubx64.efi
sudo sbctl sign -s /boot/vmlinuz-linux
sudo sbctl verify
ls /usr/share/libalpm/hooks/ | grep sbctl  # re-signe après MAJ noyau/grub

Ordre impératif : signer avant d'activer SB au firmware. Après tout grub-install, resigner (il régénère un binaire non signé). Vérif postactivation : bootctl status → SB enabled ; /sys/kernel/security/lockdown[none] ; /sys/power/state contient disk.


5. Orchestration du boot

Invariant de sûreté : BootOrder[0]=FWS en permanence. BootNext (var UEFI oneshot 8be4df61-93ca-11d2-aa0d-00e098032b8c) uniquement pour les transitions. Tout crash retombe sur FWS.

Aller FWS → Windows (/usr/local/bin/fws-gameboot to-windows, via pkexec)

Preflight avant toute écriture NVRAM — abort si un test échoue :

grep -q disk /sys/power/state                                   || die 'hibernation indispo'
awk '/^SwapTotal/{s=$2}/^MemTotal/{m=$2}END{exit !(s>=m)}' /proc/meminfo || die 'swap < RAM'
# + garde VRAM (voir §7) : image projetée <= swap
grep -q 'resume=' /proc/cmdline                                 || die 'resume= absent'
bootctl status 2>/dev/null | grep -qi 'Secure Boot: enabled'    || die 'Secure Boot inactif'
WIN=$(efibootmgr | sed -n 's/^Boot\([0-9A-Fa-f]\{4\}\)\*\? Windows Boot Manager.*/\1/p' | head -1)
[ -n "$WIN" ] || die 'entrée Windows introuvable'
findmnt -rno TARGET -t ntfs3,ntfs | while read m; do umount "$m" || true; done   # NTFS jamais rw persistante
efibootmgr -n "$WIN"
efibootmgr | grep -q "BootNext: $WIN" || { efibootmgr -N; die 'BootNext non écrit'; }  # RELECTURE obligatoire
# Watchdog anti-hang (§7) autour de :
timeout 180 systemctl hibernate || { efibootmgr -N; die 'échec/hang hibernation'; }

Retour Windows → FWS (C:\ProgramData\FWS\fws-play.ps1, compte jeu autologin)

& "$PSScriptRoot\fws-return.ps1" -Target Windows   # RE-ARME BootNext=Windows au boot -> crash/WU réatterrit sur Windows
Start-Process 'C:\Riot Games\Riot Client\RiotClientServices.exe' -ArgumentList '--launch-product=valorant','--launch-patchline=live'
do { Start-Sleep 5 } until (Get-Process VALORANT-Win64-Shipping -EA SilentlyContinue)
Get-Process VALORANT-Win64-Shipping -EA SilentlyContinue | Wait-Process   # quit OU crash
& "$PSScriptRoot\fws-return.ps1" -Target FWS        # pose BootNext=FWS
shutdown /r /t 0

Pose de BootNext côté Windows = écriture directe de la variable UEFI (SetFirmwareEnvironmentVariableExW + SeSystemEnvironmentPrivilege), repli bcdedit /set {fwbootmgr} bootsequence. Beltandsuspenders : tâche ONSTART (SYSTEM) qui arme BootNext=FWS dès le boot (couvre les crashs), + hook GPO shutdown, + powercfg /h off (reboot plein, NTFS jamais sale).

À chaque boot FWS — fws-gameboot-bootfix.service (oneshot, ConditionPathExists=!/run/archiso)

Réasserte BootOrder[0]=FWS (autoguérison anti Windows Update) et réécrit le marqueur FAT <ESP>/EFI/FWS/return.json = {fws_bootnum, windows_bootnum} (les Boot#### bougent avec efibootmgr).

Filet ultime : même mécanisme Windows HS → BootOrder[0]=FWS ramène à FWS, image d'hibernation intacte (Windows ne touche jamais l'ext4).


6. Intégration installateur FWS

Deux chemins (la cible réelle est déjà installée, sans espace libre).

Chemin NEUF (Anaconda). Nouveau spoke fws_windows.py (clone exact de fws_desktop.py, découvert au runtime, aucun rebuild) : case « Dualboot Windows (Valorant) », combo disque, spin taille (défaut 200 GiO — Win11 ~40 + Valorant ~40 + updates ; min 100). Écrit /tmp/fws-windows. Le partitionnement NTFS se fait en %pre (blivet ne sait pas créer du NTFS) :

# %pre — REMPLACE le clearpart --all destructeur (voir §7). UEFI + enabled=1 requis :
sgdisk --zap-all "$DISK"
sgdisk -n1:0:+1GiB          -t1:ef00 -c1:EFI     "$DISK"   # ESP >=1 GiO
sgdisk -n2:0:+96GiB         -t2:8200 -c2:swap    "$DISK"   # swap DÉDIÉ = RAM+VRAM -> pas de resume_offset
sgdisk -n3:0:+${WIN_GIB}GiB -t3:0700 -c3:WINDOWS "$DISK"   # slot NTFS (Microsoft basic data)
sgdisk -n4:0:0             -t4:8300 -c4:FWSROOT  "$DISK"
partprobe "$DISK"; udevadm settle
mkfs.fat -F32 ${DISK}p1; mkswap ${DISK}p2; mkfs.ntfs -Q -L WINDOWS ${DISK}p3
ignoredisk --only-use=nvme2n1        # protège nvme0n1/nvme1n1 (games)
clearpart --none
part /boot --onpart=nvme2n1p1 --fstype=efi  --noformat
part swap  --onpart=nvme2n1p2 --noformat
part /     --onpart=nvme2n1p4 --fstype=ext4
# nvme2n1p3 NON référencé -> NTFS intact ; en %post : resume=UUID=<swap> (partition dédiée, pas d'offset)

Chemin POSTINSTALL (machine réelle) — fws-windows-setup. Shrink horsligne, ordre loadbearing (cibler un NVMe games pour garder la racine intacte) :

e2fsck -f /dev/nvme1n1p1
resize2fs /dev/nvme1n1p1 1550G                      # FS sous la taille finale
parted /dev/nvme1n1 resizepart 1 1560GiB            # puis la partition
resize2fs /dev/nvme1n1p1                            # re-remplit
sgdisk -n0:0:0 -t0:0700 -c0:WINDOWS /dev/nvme1n1
mkfs.ntfs -Q -L WINDOWS /dev/nvme1n1p2

Outillage Windows (aucun bundling).

  • fws-windows-media : clé USB SecureBootpropre depuis l'ISO de l'utilisateur. install.wim >4 GiO illégal en FAT32 → FAT32 + wimlib-imagex split install.wim /usb/sources/install.swm 3800 (pas de uefintfs, bootmgfw.efi signé MS).
  • fws-windows-postinstall : lit le Boot#### « Windows Boot Manager » → /etc/fws/windows-boot-id ; efibootmgr -o <FWS>,…,<Windows> (Setup Windows se remet en tête) ; vérifie SB/TPM2/VBS ; rappels DANS Windows : powercfg /h off, NE PAS activer BitLocker (ou suspendre aux bascules).

7. Risques & mitigations (revue adversariale intégrée)

# Sévérité Problème Mitigation retenue
1 BLOQUANT clearpart --all --disklabel=msdos inconditionnel dans interactive-defaults.ks → efface les 3 NVMe (dont games) + force MBR sur UEFI. Ne jamais livrer l'ISO en l'état. %pre conditionné /sys/firmware/efi + ignoredisk --only-use + clearpart --none + part --onpart sur layout sgdisk. Protéger nvme0/1 explicitement. Tester sur ISO.
2 BLOQUANT Resume GPU cassé : RTX 5090 Blackwell sans PreserveVideoMemoryAllocations → écran noir/corruption au S4. Design muet sur le GPU. NVreg_PreserveVideoMemoryAllocations=1 + NVreg_TemporaryFilePath ; nvidia-hibernate/resume actifs ; tester le resume session chargée AVANT de câbler le bouton ; fallback reboot obligatoire si échec (Phase 4).
3 Majeur Swap = RAM ignore la VRAM recopiée (jusqu'à 32 Go) → image 7590 GiO > swap 64 → échec. Swap = RAM + VRAM + marge = 96 GiO. Preflight : estimer VRAM en usage (nvidia-smi), refuser/basculer reboot si image projetée > swap. Tester pire cas (jeu déjà lancé côté Linux).
4 Majeur Brick FWS par révocation dbx/SBAT poussée par Windows Update (précédents BootHole/SBAT réels). Windows booté fréquemment ici → risque élevé. shim/grub à jour et resignés ; différer/figer Windows Update sur ce Windows gaming minimal ; tester bascule après chaque MAJ Windows/Vanguard ; fournir un média de récupération FWS (ré‑enrôlement/resignature).
5 Majeur BitLocker autoactivé par TPM+SB (Win11 25H2 Device Encryption) : le flip SB OFF→ON change PCR7 → écran de récupération, clé dans le compte MS. Activer Secure Boot AVANT d'installer Windows (PCR7 stable dès l'install, pas de flip). Documenter : suspendre/désactiver BitLocker, sauvegarder la clé, powercfg /h off. Vérifier deviceencryption au postinstall et alerter. Nuance : les bascules BootNext récurrentes ne touchent PAS PCR7 (bootmgfw chargé à l'identique).
6 Majeur systemctl hibernate qui hang (driver refuse S4) : machine allumée, session ni sauvée ni basculée, BootNext=Windows resté armé → départ surprise. ⚠️ NON mitigeable en userspace : pendant un hang S4 le process (et tout watchdog) est gelé — un timeout est impossible (il tuerait aussi les hibernations réussies, qui ne rendent la main qu'au resume). Parades réelles : préflight strict (élimine les causes courantes) + auto-guérison au reset (BootNext=Windows → Windows → tâche ONSTART arme FWS → retour) + filet BootOrder[0]=FWS. Tester la robustesse S4 sur la carte ; documenter la récupération post-hang.
7 Majeur Resume silencieux en échec (offset dérivé/image corrompue) → cold boot, session perdue sans notification. Incohérence swapfile+offset (fragile) vs partition dédiée (robuste). Unifier sur partition swap dédiée dès que possible (chemin installeur) ; chattr +i sur tout swapfile résiduel ; revalider l'offset au preflight ET au retour ; notifier explicitement « session non restaurée » au cold boot posthibernation.
8 Majeur Politique de fallback contradictoire entre docs (`hibernate
9 Majeur Sémantiques BootNext/BootOrder non validées (Windows pas installé) : firmware peut ignorer BootNext, réordonner, purger l'entrée FWS. Mapping bcdedit {fwbootmgr} → BootNext non documenté MS. Valider empiriquement dès la 1re install (écrire BootNext côté Windows, relire via efibootmgr côté Linux). Entrée de secours \EFI\BOOT\BOOTX64.EFI (grub-install --removable). Ne pas dépendre que de BootNext.
10 Majeur Prérequis SB non résolu : grubx64.efi sans .sbat ni shim_lock → shim refuse GRUB ; grub-install régénère non signé. Réinstall GRUB (--sbat + modules) + signature avant d'activer SB ; hooks resignature couvrant linux + LTS/fallback ; vérifier objdump 'sbat' ; ne jamais activer SB sans sbverify OK (§4).
11 Mineur Fondement « bit CPUID hyperviseur = 0 » FAUX : Zen 5 + Win11 25H2 → VBS/HyperV actif, bit=1, toléré par Vanguard. Ne pas combattre VBS. Corriger la doc : Vanguard vérifie SB actif + TPM présent + absence d'hyperviseur TIERS, pas un bit à 0. Valider que Valorant lance avec VBS on par défaut.
12 Mineur SB sans lockdown côté Linux = conformité, pas défense : initramfs non signé, grub.cfg éditable, image d'hibernation en clair sur ext4. Assumer honnêtement (SB ici = case Vanguard). Durcissement horsMVP : UKI cmdline scellée, LUKS+TPM sur le swap (impose repartition).
13 Mineur Risque fournisseur Vanguard (changement de politique) + overhead ~35 min/session. Compat annoncée besteffort, retest après chaque bump. Offrir un mode « reboot simple » (sans hibernation) comme voie robuste par défaut, hibernation en confort optin → réduit drastiquement la surface de brick/perte de session.

8. Décisions ouvertes à trancher avec l'utilisateur

  1. Hibernation vs reboot simple par défaut. La couche hibernation ajoute VRAM/offset/resume fragiles pour ~35 min gagnées. Recommandation revue : reboot simple robuste par défaut, hibernation optin. À arbitrer (c'est un choix produit majeur).
  2. Swap : partition dédiée (repartition, robuste, sans offset) vs swapfile 96 GiO (aucun repartition, offset fragile). Sur la machine déjà pleine, swapfile pragmatique ; sur install neuve, partition dédiée. Unifier ?
  3. Chiffrement de l'image d'hibernation (MVP en clair vs LUKS+TPM d'emblée). Conditionne planning et gestion PCR.
  4. Voie Secure Boot : sbctl (db custom, reco) vs shim+MOK (plus robuste OEM, prompt MokManager). Dépend de l'acceptation du firmware pour l'enrôlement db custom.
  5. Disque Windows : shrink de la racine nvme2n1 (même NVMe que l'ESP) vs un NVMe games (nvme1n1, boot crossdisque). Quel disque l'utilisateur sacrifie ?
  6. ESP partagée 512 MiO vs ESP Windows dédiée lors du carveout (512 MiO très juste avec bootmgfw + noyaux + marqueur return.json).
  7. NTFS pré‑formaté (mkfs.ntfs -Q) vs espace non alloué + MSR pour des mesures PCR/BitLocker les plus propres (à trancher par test).
  8. Retour auto (watcher WMI, risque heuristique AV) vs bouton manuel (défaut reco = manuel).
  9. Bootstrap Windows : FWS pilote l'install (autounattend/SetupComplete, le plus propre) vs RunOnce offline sur Windows existant.
  10. Politique clé de signature FWS : commune dans l'ISO (simple, fuite = compromission de flotte) vs générée par machine (sûre, non industrialisable en masse).
  11. Taille NTFS par défaut : 150 vs 200 GiO (recommandation : 200).
  12. Différer/figer Windows Update sur le Windows gaming (mitigation brick dbx/SBAT #4) — acceptable pour l'utilisateur ?

Portes bloquantes avant tout ship : (a) kickstart rendu non destructif et testé sur ISO ; (b) resume GPU NVIDIA validé session chargée ; (c) swap ≥ RAM+VRAM ; (d) GRUB signé+.sbat avant activation SB ; (e) BootNext validé empiriquement sur la carte mère ; (f) média de récupération FWS prêt.