# DF-3809 — port_to_transcoder[PORT_F] out-of-bounds read on GEN9_BC (SKL/KBL/CFL) DDI F

## File
`sys/dev/drm/i915/intel_ddi.c:3180-3187` (`intel_enable_ddi_hdmi`, Display WA #1143)

## Build / Run / Expected
**Not built, not run — guest has no Intel graphics** (DragonFly QEMU guest: std VGA, no
i915/drm0 attachment — see `env.txt`). Source-level finding.

Hypothetical trigger on affected hardware: boot a GEN9_BC part (SKL/KBL/CFL,
`IS_GEN9_BC()` = `IS_GEN9() && !IS_LP()`, i915_drv.h:2562) whose `SFUSE_STRAP`
reports `SFUSE_STRAP_DDIF_DETECTED` (i915_reg.h:9664) and whose VBT declares port F
DP/HDMI/DVI capable, then userspace enables an HDMI mode on that port (any modeset
via drm ioctls). Expected: `port_to_transcoder[5]` reads past the 5-element array.

## Root cause
The WA #1143 lookup table covers PORT_A..PORT_E only:

```c
static const enum transcoder port_to_transcoder[] = {
        [PORT_A] = TRANSCODER_EDP,
        [PORT_B] = TRANSCODER_A,
        [PORT_C] = TRANSCODER_B,
        [PORT_D] = TRANSCODER_C,
        [PORT_E] = TRANSCODER_A,
};
enum transcoder transcoder = port_to_transcoder[port];   /* port == PORT_F == 5 -> OOB */
```

`intel_display.c:14340-14341` constructs PORT_F DDI encoders inside the `HAS_DDI()`
branch (which includes all GEN9_BC parts) whenever the DDIF strap bit is set, and
`intel_ddi_init()` completes for the port because every helper it uses
(`intel_port_to_power_domain`, `intel_ddi_max_lanes`, `intel_infoframe_init`)
handles PORT_F. Only this WA array does not. The OOB read lands in adjacent
.rodata; the garbage `transcoder` value is then used to compute
`CHICKEN_TRANS(transcoder)` — an MMIO write with an attacker-uncontrolled but
out-of-range register offset (bits set then cleared).

## Impact
Wrong-register MMIO writes during HDMI enable on DDI F of an affected part:
display-state corruption / potential GPU hang. No proven control over the offset
or data beyond two fixed bits. Severity: Low.
