Session 21 — 2026-03-27d
| Field | Value |
|---|---|
| Date | 2026-03-27 |
| Phase | 03b — TWRP |
| Duration | ~2.5 h |
EBC Ioctl Numbers — Confirmed via Ghidra
| Ioctl | Value | Purpose |
|---|---|---|
| EBC_SEND_UPDATE | 0x700c | Trigger EPDC refresh |
| EBC_WAIT_UPDATE | 0x700d | Wait for completion |
| EBC_CLEAR | 0x700e | Clear screen |
Update struct (40 bytes, passed to 0x700c)
struct onyx_epdc_update {
int32_t y; // offset 0
int32_t x; // offset 4
int32_t width; // offset 8
int32_t height; // offset 12
int32_t waveform_mode; // offset 16: 1=DU, 2=GC16, 0xff=auto
int32_t update_mode; // offset 20: from mode >> 5
int32_t marker; // offset 24: sequence counter
int32_t dither; // offset 28: 0x28 or 0x1000
uint32_t flags; // offset 32: 0x20000 (stock)
int32_t reserved; // offset 36: 0
};
Stock code never calls FBIOPUT_VSCREENINFO or FBIOPAN_DISPLAY. Flow: syncDataToExtendedBuffer (row-by-row copy to ebc mmap, pixel_stride=7488 not row_bytes=7552) → refreshScreen (ioctl 0x700c).
TWRP v1.7–v2.5 Iterations
| Version | Change | Result |
|---|---|---|
| v1.7 | ebc open + ioctl + buffer copy | Double buffer; hung on first flip |
| v1.8 | Forced single buffer, hardcoded | SIGSEGV — stride mismatch (7552 vs 7488) |
| v1.9 | Skip ebc buffer copy, ioctl only | No crash. Kernel receives ioctl. No display change. |
| v2.0–v2.4 | Row-by-row copy; test patterns; stock mode values; FBIOBLANK | All: ioctl accepted, logged by kernel, no display change |
| v2.5 | Added FBIOPUT_VSCREENINFO yoffset=0 | Built but session ended |
Kernel log: SET_EBC_SEND_UPDATE -- magic[N] [x=0 y=0 w=1872 h=1404]! flags=0x20000! — the ioctl entry point runs and logs parameters, but no pixels reach the panel. Problem is below the ioctl dispatch — in MDSS pipeline state, onyx_epdc_put_image, or _epdc_update_wb_direct.
Build System Learnings
- Added
device/onyx/noteair1/src-overlay/mechanism — files copied over TWRP source before build; updatedtools/twrp-buildaccordingly RECOVERY_GRAPHICS_FORCE_SINGLE_BUFFERflag unreliable with Soong cache — hardcode in source overlay instead- Must delete stale
libminuitwrp.soin recovery ramdisk staging and*relink*files before each build
Conclusion
Trial-and-error ioctl parameter tuning is exhausted. Strace of the stock recovery binary is the definitive next step to find what initialization step we are missing.