# DF-4853 — evergreen_hdmi_enable/evergreen_dp_enable consume lvds-typed enc_priv (DF-4635/DF-4828 family, new sinks, eDP-dpms trigger)

## What

`evergreen_hdmi_enable()` (sys/dev/drm/radeon/evergreen_hdmi.c:429-461) and
`evergreen_dp_enable()` (:470-514) load `radeon_encoder->enc_priv` as
`struct radeon_encoder_atom_dig *` and guard only `if (!dig || !dig->afmt)`
(:431, :473). For LCD-carrying digital encoders — **every eDP panel** —
enc_priv is a 280-byte `radeon_encoder_lvds` (atombios_encoders.c:2862-2869,
UNIPHY*/KLDSCP_LVTMA/DDI/DVO1 with ATOM_DEVICE_LCD_SUPPORT, and TMDS1/LVTM1
at :2824-2836), so:

* `dig->afmt` at +288 reads **8 bytes past the 280-byte object** (280 rounds
  to a 288-byte slab chunk, zero slack) = the first 8 bytes of the ADJACENT
  kernel object;
* the NULL-guard *consumes* that garbage; if non-NULL it falls through and
  `dig->afmt->offset` (wild read) drives six WREG32/WREG32_AND/WREG32_OR
  sites (:438-455), and `dig->afmt->enabled = enable` (:458, :513) is a
  **wild write through the OOB-read pointer** on every dpms transition.

## Trigger (why this is NOT covered by DF-4828's dismissal)

DF-4828's verdict dismissed the dpms path: "r600_hdmi_enable is only
reachable via radeon_audio_dpms, which is gated on encoder_mode == HDMI ||
DP — the mis-typed LVDS-mode encoders never take it". That misses **eDP**:

1. eDP panel encoder = INTERNAL_UNIPHY* + ATOM_DEVICE_LCD_SUPPORT →
   registered `DRM_MODE_ENCODER_LVDS`, `enc_priv = radeon_encoder_lvds*`
   (atombios_encoders.c:2862-2869);
2. eDP connector detect → `radeon_dp_detect` (radeon_connectors.c:1764-68)
   → `radeon_audio_detect` (radeon_audio.c:444): connector_type == eDP
   (≠ DRM_MODE_CONNECTOR_DisplayPort) → else branch →
   **`radeon_encoder->audio = rdev->audio.hdmi_funcs`** (radeon_audio.c:471;
   DCE4+: `.dpms = evergreen_hdmi_enable`, radeon_audio.c:206);
3. any dpms transition: `radeon_atom_encoder_dpms`
   (atombios_encoders.c:1836) → `atombios_get_encoder_mode` → eDP connector
   ⇒ **`ATOM_ENCODER_MODE_DP`** (atombios_encoders.c:824-829) → the gate at
   :1848-1851 **passes** (ENCODER_MODE_IS_DP) → `radeon_audio_dpms`
   (radeon_audio.c:777-783) → **`evergreen_hdmi_enable`** with the
   mis-typed enc_priv.

So on any DCE4+ (evergreen/NI/SI) laptop with an eDP panel and audio
enabled, every screen blank/unblank/mode-set walks the corrupted path.
`evergreen_dp_enable` is the DP-sink twin (reachable if a DisplayPort-class
connector is served by an LCD-carrying encoder).

Sibling in another file (noted for the queue):
`atombios_get_encoder_mode` itself derefs enc_priv as atom_dig
(`dig_enc->active_mst_links`, atombios_encoders.c:741-744, +304 OOB read).

## Reproduce (live-allocator harness; no radeon GPU on this guest)

```sh
cd /tmp/df4853 && cc -O -o evg_offsets evg_offsets.c && ./evg_offsets
make && kldload -v /tmp/df4853/evg_probe.ko && kldunload evg_probe
```

Expected (run.log): `dig->afmt` (+288) reads the groomed adjacent-chunk
pointer, the :431 guard FALLS THROUGH, `dig->afmt->offset` (0x5678) feeds
the MMIO sites, and `dig->afmt->enabled` flips 0→1→0 through the OOB-read
pointer; zeroed neighbor = silent return (field-hiding case).

## Files

`evg_offsets.c` (geometry: lvds=280, atom_dig=312, afmt@+288),
`evg_dpms_probe.c` + `Makefile` (KLD harness), `build.sh`, `run.log`,
`build.log`, `fix_build.log` (patched radeon.ko, -Werror), `fix.diff`,
`VERDICT.md`, `env.txt`.
