# DF-5236 — hw_translate_diag.c all-NULL function table (Info, latent, FPGA-gated)

File: `sys/dev/drm/amd/display/dc/gpio/diagnostics/hw_translate_diag.c` (pass 2)

## What

`funcs` (hw_translate_diag.c:34-37) is a `struct hw_translate_funcs` with **both**
members explicitly NULL (`offset_to_id = NULL`, `id_to_offset = NULL`).
`dal_hw_translate_diag_fpga_init()` (hw_translate_diag.c:39-42) installs this table
and returns — reporting success — with no functional translator whatsoever.

## Why it is only Info (unreachable on this tree)

The sole caller is `dal_hw_translate_init()` (hw_translate.c:61-63), which installs
the diag table only when `IS_FPGA_MAXIMUS_DC(dce_environment)` is true
(dc_types.h:58-59, i.e. `dce_environment == DCE_ENV_FPGA_MAXIMUS`).

`enum dce_environment` (dc_types.h:46-55) has `DCE_ENV_PRODUCTION_DRV = 0`. The
**only** assignment in the entire driver is hardcoded:

  sys/dev/drm/amd/display/amdgpu_dm/amdgpu_dm.c:424:
      init_data.dce_environment = DCE_ENV_PRODUCTION_DRV;

copied verbatim into the dc context at core/dc.c:624 and passed to
`dal_gpio_service_create()` at core/dc.c:661-663. There is no module parameter,
sysctl, ioctl, debugfs entry, or device property in this tree that can select
`DCE_ENV_FPGA_MAXIMUS`. Zero-initialization is also safe (0 == production).
`dal_hw_translate_diag_fpga_init` is therefore dead code on DragonFlyBSD — same
proof shape as the i2caux diag twin and DF-5231 (hw_factory_diag.c, Info).

## Impact if ever activated (e.g. someone flips the env or imports the diag env)

First GPIO operation would be an immediate NULL function-pointer call — kernel
panic at boot/DC-init:

  gpio_service.c:151  `service->translate.funcs->offset_to_id(...)`   (create_irq)
  gpio_service.c:418  `service->translate.funcs->offset_to_id(...)`   (create_ddc)
  gpio_base.c:144     `gpio->service->translate.funcs->id_to_offset(...)` (get_pin_info)

Not attacker-steerable: the table is a compile-time constant of NULLs; there is
no write primitive, only call-through-NULL. Panic-only, latent, gated off.

## Negative results (why nothing worse hides here)

- Unknown-ASIC path cannot leak the NULL table: `dal_hw_translate_init()` default
  case returns false (hw_translate.c:92-94) and `dal_gpio_service_create()`
  handles it (gpio_service.c:69-73: BREAK_TO_DEBUGGER; goto failure_1; kfree;
  return NULL) — production always gets a fully-populated ASIC table.
- No other caller of `dal_hw_translate_diag_fpga_init` exists (tree-wide grep).
- Nothing else in the 42-line file: no state, no allocation, no locking concerns.

## PoC status

`untested` — static-analysis-only Info/hardening finding. The trigger requires a
source change (forcing DCE_ENV_FPGA_MAXIMUS), i.e. it is not reachable on a
shipped kernel; per audit contract Phase V is not run for Info findings. If a
maintainer wants a live demonstration, the 2-line patch in fix.diff applied
together with `init_data.dce_environment = DCE_ENV_FPGA_MAXIMUS;` panics at
`dal_gpio_service_create_irq` on any amdgpu ASIC (expected `call 0x0` trap).

## Fix

See fix.diff: replace the NULL entries with explicit false-returning stubs (or
delete the diagnostics twins from the build — Makefile:252 builds them for
nothing). Family-consistent with DF-5231's recommendation.
