feat(fws-gameboot): add game selection support for windows boot with --game option

Add ability to specify which game to launch on Windows via --game CLI argument.

- Introduce FWS_DEFAULT_GAME environment variable (defaults to 'valorant')
- Parse --game option in to-windows command to override default
- Sanitize game identifiers using lowercase and allowed chars [a-z0-9_-]
- Write atomic game token (launch.json) to ESP FAT partition for Windows to consume
- Purge stale tokens on write failure to prevent replay of old choices
- Update help text with new option and game identifier constraints
This commit is contained in:
2026-07-08 03:20:50 +02:00
parent 810a98fc34
commit 9b80effc77
@@ -27,6 +27,7 @@ CONF=/etc/fws/gameboot.conf
: "${FWS_WINDOWS_BOOTNUM:=}"
: "${FWS_HIBERNATE_FALLBACK:=reboot}"
: "${FWS_SWAP_MARGIN_MB:=2048}"
: "${FWS_DEFAULT_GAME:=valorant}"
log() { printf '\e[36m[gameboot]\e[0m %s\n' "$*" >&2; }
warn() { printf '\e[33m[gameboot] %s\e[0m\n' "$*" >&2; }
@@ -115,11 +116,42 @@ cmd_doctor() {
cmd_to_windows() {
need_root "to-windows"
local win esp bootnext_set="" rc m
local win esp tok bootnext_set="" rc m game="${FWS_DEFAULT_GAME:-valorant}" game_req=""
while [ $# -gt 0 ]; do
case "$1" in
--game) game="${2:-}"; game_req=1; shift 2 ;;
--game=*) game="${1#--game=}"; game_req=1; shift ;;
*) die "argument inconnu : $1 (usage : to-windows [--game <id>])" ;;
esac
done
# Charte d'identifiant alignée sur les clés de games.json : [a-z0-9_-]
# (l'underscore doit passer, sinon divergence FWS↔Windows).
game="$(printf '%s' "$game" | tr '[:upper:]' '[:lower:]' | tr -cd 'a-z0-9_-')"
[ -n "$game_req" ] && [ -z "$game" ] && warn "identifiant --game invalide après nettoyage — jeu par défaut appliqué."
win="$(find_windows_bootnum)"
[ -n "$win" ] || die "entrée « Windows Boot Manager » introuvable (Windows installé + entrée UEFI présente ?)"
esp="$(find_esp)"
# Jeton « quel jeu lancer », lu ET CONSOMMÉ par fws-play côté Windows.
# Écriture ATOMIQUE (.tmp puis mv) sur l'ESP FAT uniquement. En cas d'échec,
# on PURGE tout jeton périmé (jamais de rejeu d'un ancien choix) → Windows
# lancera le jeu par défaut plutôt qu'un mauvais jeu.
if [ -n "$esp" ] && [ "$(findmnt -no FSTYPE "$esp" 2>/dev/null)" = vfat ]; then
if [ -n "$game" ]; then
mkdir -p "$esp/EFI/FWS" 2>/dev/null || true
tok="$esp/EFI/FWS/launch.json"
if printf '{"game":"%s"}\n' "$game" > "$tok.tmp" 2>/dev/null && mv -f "$tok.tmp" "$tok" 2>/dev/null; then
log "Jeu demandé : $game"
else
rm -f "$tok" "$tok.tmp" 2>/dev/null || true
warn "écriture du jeton échouée → jeton purgé (Windows lancera le jeu par défaut)."
notify_user "Choix du jeu non transmis — Windows lancera le jeu par défaut."
fi
fi
elif [ -n "$game_req" ]; then
warn "ESP FAT introuvable → le choix du jeu ne peut pas être transmis à Windows."
fi
# Filet : ne JAMAIS laisser BootNext armé si on ne bascule pas réellement
# (sinon départ surprise vers Windows au prochain reboot manuel).
cleanup() { [ -n "$bootnext_set" ] && { efibootmgr -N >/dev/null 2>&1 || true; log "BootNext annulé (nettoyage)"; }; }
@@ -201,17 +233,20 @@ usage() {
cat <<EOF
fws-gameboot — dual-boot hibernate-swap (FWS ⇄ Windows bare-metal, anticheat kernel)
fws-gameboot doctor Vérifie l'environnement (préflight, entrées de boot)
fws-gameboot to-windows Hiberne FWS et bascule vers Windows (root/pkexec)
fws-gameboot doctor Vérifie l'environnement (préflight, boot)
fws-gameboot to-windows [--game <id>] Hiberne FWS, bascule + lance <id> (root/pkexec)
fws-gameboot status Alias de « doctor »
Le jeu par défaut (FWS_DEFAULT_GAME) est « valorant ». Les identifiants connus
sont définis dans games.json côté Windows (valorant, lol, …).
Config : $CONF
Détails et risques : docs/hibernate-swap-dualboot.md
EOF
}
case "${1:-}" in
to-windows) cmd_to_windows ;;
to-windows) shift; cmd_to_windows "$@" ;;
doctor|status) cmd_doctor ;;
''|-h|--help|help) usage ;;
*) die "sous-commande inconnue : $1 (voir --help)" ;;