# DF-5197 — warp_saver ignores set_video_mode() failure: stale 32KB text va_window would take a 64KB bzero + star writes 32KB past it (DF-5114 twin)

File: `sys/dev/misc/syscons/warp/warp_saver.c:85-95`

## What

```c
if (blanked <= 0) {
    crit_enter();
    set_video_mode(adp, M_VGA_CG320);      /* :87 — return value ignored */
    load_palette(adp, warp_pal);
    ...
    vid = (u_char *)adp->va_window;        /* :93 */
    crit_exit();
    bzero(vid, SCRW*SCRH);                 /* :95 — 64000 bytes */
}
```

`set_video_mode()` (fbreg.h:120-121) dispatches to `vga_set_mode()`
(sys/dev/video/fb/vga.c:997) which can fail — `prologue(adp,
V_ADP_MODECHANGE, ENODEV)` (adapter without mode-change / being
detached) or `vga_get_info(...)` → EINVAL. **On failure it returns
before `update_adapter_info()`**, so `adp->va_window` still describes
the *text* mode: CGA_BUF_BASE = 0xB8000 with CGA_BUF_SIZE = 0x8000
(32KB) (sys/dev/video/fb/vgareg.h:37-38, vga.c:274-275). warp_saver
then:

- `bzero(vid, 64000)` clears 0xB8000..0xC7BFF — **32,000 bytes past
  the 32KB text window**, into 0xC0000-0xC7C00 (video-BIOS ROM-shadow
  region on BIOS systems: writes fault or are silently dropped
  depending on platform);
- every subsequent `warp_update()` tick writes star pixels anywhere
  in [0,64000] of that same stale window.

Contrast with a *successful* switch: va_window = 0xA0000, window size
GRAPHICS_BUF_SIZE = 0x10000 (64KB) (vga.c:581, vgareg.h:43-44), where
64000 bytes fit.

This is the exact twin of DF-5114 (dragon_saver.c:194,
`set_video_mode(adp, VIDEO_MODE);` ignored), which pass 1 graded
Info / latent: warp_init() already verified `get_mode_info(adp,
M_VGA_CG320) == 0` at module load (warp_saver.c:114-117), and
`vga_set_mode()` re-runs the same `vga_get_info()` — so the failure
requires adapter state to diverge between load and first blank
(detach, V_ADP_MODECHANGE cleared). No in-tree path produces the
trigger today; hence Info, not higher.

## Fix (infrastructure-compatible)

`scsplash_saver()` already handles `EAGAIN` from the splash layer
(sys/dev/misc/syscons/syscons.c:2564-2567: restores saver mode, touches
the saver timestamp, retries later). Return it:

```diff
--- a/sys/dev/misc/syscons/warp/warp_saver.c
+++ b/sys/dev/misc/syscons/warp/warp_saver.c
@@ -83,8 +83,11 @@ warp_saver(video_adapter_t *adp, int blank)
     if (blank) {
 	/* switch to graphics mode */
 	if (blanked <= 0) {
 	    crit_enter();
-	    set_video_mode(adp, M_VGA_CG320);
+	    if (set_video_mode(adp, M_VGA_CG320) != 0) {
+		crit_exit();
+		return EAGAIN;	/* scsplash_saver() retries later */
+	    }
 	    load_palette(adp, warp_pal);
```

`blanked` stays 0 and `vid` is not captured, so no stale-window state
is committed.

## Why untested (Phase V skipped)

Info / latent finding per contract (and consistent with DF-5114's
grading): there is no in-tree producer of the failure after a
successful init-time get_mode_info, so a guest PoC cannot reach the
bad path without artificially patching the kernel (which would test
the patch, not the tree). The one-line code-shape defect is certain
by inspection; the trigger is speculative.
