# DF-5198 — fire_saver(): set_video_mode() return ignored (DF-5114/DF-5197 twin)

File: `sys/dev/misc/syscons/fire/fire_saver.c` (pass 2, GLM 5.3)
Severity: Info · bucket: memcorrupt · confidence: certain (shape) / latent (trigger)

## What

`fire_saver()` ignores the return value of `set_video_mode(adp, M_VGA_CG320)`
(fire_saver.c:69) and then, unconditionally, every saver tick:

```c
vid = (u_char *) adp->va_window;            /* fire_saver.c:85 */
...
memcpy(vid, buf, X_SIZE * Y_SIZE);          /* fire_saver.c:104 — 64000 bytes */
```

If the mode switch failed, `adp->va_window` still aliases the **32 KB text-mode
window** (0xB8000), and the 64000-byte `memcpy` (plus every fade-tick write
path feeding it) overruns that window by ~32 KB into 0xC0000+ (video BIOS
shadow / adapter MMIO — not kernel RAM). This is the exact DF-5114
(dragon_saver.c) / DF-5197 (warp_saver.c) twin, completing the family sweep
in the last syscons saver file.

## Why it is latent on the stock kernel

`fire_initialise()` (fire_saver.c:118) gates module registration on
`get_mode_info(adp, M_VGA_CG320, &info)` succeeding — and `vga_set_mode()`
(vga.c:997) can only fail via:

- `prologue(adp, V_ADP_MODECHANGE, ENODEV)` (vga.c:1003; macro at vga.c:414):
  requires `!vga_init_done` or the adapter flag `V_ADP_MODECHANGE` clear —
  the flag is set once at vga.c:684 and never cleared at runtime (only read
  at vga.c:888/1003/2007);
- `vga_get_info(adp, mode, &info)` → EINVAL (vga.c:1005-1006) when
  `get_mode_param(mode) == NULL` (vga.c:888-893) — the *same* check
  `fire_initialise` already passed on the same adapter (splash_adp is set
  from sc->adp at syscons attach, syscons.c splash_init call).

So on a stock single-adapter VGA system the failure branch is unreachable:
`set_video_mode` deterministically agrees with the earlier `get_mode_info`.
The gap is defensive (a future adapter/driver whose set_mode can fail
asynchronously, or a multi-adapter splash_adp ≠ sc->adp setup), identical in
kind to the two accepted twins.

## Reproduce (live benign-path exercise)

```
vm.sh run_root 'kldload fire_saver && echo KLDLOAD_OK; \
  vidcontrol -t 1 < /dev/ttyv0 && echo ARMED; sleep 5; \
  vidcontrol -t 600 < /dev/ttyv0 && echo REARMED_OK; sleep 2; \
  vidcontrol -t 3 < /dev/ttyv0; sleep 8; vidcontrol -t 600 < /dev/ttyv0; \
  sleep 2; echo SECOND_CYCLE_DONE'
```

Expected on stock kernel: module loads (get_mode_info passes), the fire
renders for two blank cycles (~13 s ≈ 500 fade+blit ticks), unblank restores
the text console, no panic. That is what was observed (run.log). The
out-of-window write itself cannot be triggered on this guest without
modifying vga.c — hence `not_reproduced`/latent, matching the DB treatment of
DF-5114 and DF-5197 (`untested`, "latent out-of-window video MMIO writes (not
kernel RAM)").

## Artifacts

- `run.log` — full untrimmed output of both guest sessions
- `env.txt` — guest uname, dmesg (sc0/vga0), kldstat, module list
- `trigger.sh` / `run.sh` / `build.sh` — exact commands
- `fix.diff` — guard the mode switch, bail out with ENODEV on failure
- `VERDICT.md`, `manifest.json`, `verdict.json`
