Round 3: still black with the corrected OVL_EN offset. All device-era
display_cleanup steps are now provably undone, and init_screen()
sequencing proves the menu was drawn into the LBIO physical_address
(OVL_L0_ADDR == pa), so revival + fills are correct on paper. The
unexcluded branch: the payload may never execute — internal boot of a
custom p1 image was never baseline-proven on this device.
Diagnostic payload (9d7859dc...):
- first instructions: OVL_EN=1, OVL0_2L_EN=1, backlight on (no parse)
- parse failure: 5 slow backlight blinks, spin
- parse success: red -> yellow -> green -> blue, blue held
Decision tree: colors = pipeline validated; blinks on black = parse
failed at runtime; nothing = payload never handed off.
An earlier design read OVL_L0_ADDR pre-parse; abandoned: unassigned
MMIO reads data-abort on qemu -M virt (killed the test) and would do
the same on hardware with a gated display clock. The stub now has no
MMIO reads.
host_test and qemu_test pass; flashed and verified on device.
Round-1 revival wrote the overlay-enable register at 0x14008000+0x0F00;
depthcharge's mtk_ddp.c (2021 revision 497450b4, current tree, merge
commit 74376061, and Linux mtk_disp_ovl.c) defines DISP_REG_OVL_EN at
0x000C. The wrong-register write left the OVL engine disabled, so all
checkpoint fills were invisible (Round 2: black screen with payload
verified intact on mmcblk0p1).
Also: resolve the open physical_address question in RESEARCH.md (LBIO
fb addr is provably non-zero at runtime — mtk_display_init programs
OVL_L0_ADDR from the LBIO record and the dev menu rendered through it),
and log the /dev/mem live-read result (STRICT_DEVMEM + reserved RAM,
'Bad address' rather than EPERM).
Rebuilt payload sha256 9e7cf29d... verified on device (cmp + vbutil
body verification). host_test and qemu_test pass.
Chronological record of the research: source verification (coreboot
tables, arm64 Image header, depthcharge FIT loader), the first black-
screen attempt, the depth-charge-version forensics that identified the
handoff teardown (black fill + backlight GPIOs + OVL_EN off), the
register-level facts used for the revival fix, flash state, and a
post-fix diagnostic decision tree.
Root cause of the black screen, verified against the DEVICE's
depthcharge (v0.0.22-10476, ChromeOS R93-era): display_cleanup() runs
at CleanupOnHandoff before jumping to the payload and
1. clears the LBIO framebuffer to black,
2. drives DISP_PWM (GPIO 43) and EN_LCD_BL (GPIO 176) low,
3. disables the OVL engines (OVL_EN=0, OVL0_2L_EN=0).
DSI/panel/MTCMOS remain up (panel poweroff only exists in 2025+ code),
so the stub just undoes those three steps: re-enable both OVLs, set
both backlight GPIOs, then paint. The OVL_L0_ADDR register still points
at the menu framebuffer, which is the LBIO record address our parser
already extracts.
The live environment boots from the USB stick; the eMMC kernel
partition is not load-bearing, so it is the safer first target.
Document backup locations, flash/verify commands, and recovery.
Backup of /dev/mmcblk0p1 taken before any write.
Strengthen the qemu end-to-end test: sample the framebuffer first pixel
every 0.5s for ~9s of stub time and require the exact transition order
red -> yellow -> green -> blue with no further transitions, plus a
final full-screen uniform-blue snapshot. Update README with run
instructions. All checks pass.
Minimal freestanding arm64 binary that depthcharge boots as a kernel:
parses depthcharge's /firmware/coreboot DTB node, walks the coreboot
table, finds LB_TAG_FRAMEBUFFER, and paints red/yellow/green/blue
checkpoints (~2s each) into the live boot-splash framebuffer.
Verified against coreboot tables header, Linux arm64 booting.rst, and
depthcharge's fit.c/boot64.c. Host parser tests pass against the live
/sys/firmware/fdt; full red->yellow->green->blue sequence verified
end-to-end under qemu-system-aarch64; packed image verifies with the
ChromeOS devkeys.