diff --git a/RESEARCH.md b/RESEARCH.md index 5b35082..803f0ca 100644 --- a/RESEARCH.md +++ b/RESEARCH.md @@ -385,6 +385,21 @@ The OVL register READ is device-only (qemu -M virt aborts on reads to unassigned MMIO; qemu never takes the failure/substitution path, so the test is unaffected). +## Round 8 — hex-digit diagnostic dump + +The bit-band dump WAS visible at the L0_ADDR scanout (proving both the +scanout substitution and the render path), but 32 coarse squares per row +proved unreadable from a photo, and the apparent row/column confusion +made transcription unreliable. The dump rendering is replaced with +**giant hex digits**: one u32 per line, 8 digits of a 3x5 cell font +scaled x10 (30x50 px), MSB nibble first, white on depthcharge's black +background. Readable in any panel orientation, transcribable as text. +Same data, same markers (`0xC0DE0001` DTB stage, `0xC0DE0002|rc` LBIO +stage, word 15 = raw OVL_L0_ADDR value). + +Payload `10760e3c…` flashed (cmp + vbutil OK). host_test and qemu_test +pass. + Recovery: power-cycle, boot USB (unchanged), `dd if=mmcblk0p1-pmos-backup.img of=/dev/mmcblk0p1 bs=4M conv=fsync`. diff --git a/krane-fb-stub-payload.bin b/krane-fb-stub-payload.bin index 866cde4..7ba97d5 100644 Binary files a/krane-fb-stub-payload.bin and b/krane-fb-stub-payload.bin differ diff --git a/krane-fb-stub.bin b/krane-fb-stub.bin index 3dd769a..0755edd 100755 Binary files a/krane-fb-stub.bin and b/krane-fb-stub.bin differ diff --git a/main.c b/main.c index bb89838..563eb0c 100644 --- a/main.c +++ b/main.c @@ -313,34 +313,66 @@ static void stage0(void) /* ---- failure diagnostics ------------------------------------------------- * - * The parse failed. Paint the failing values as bit-bands directly into - * the live scanout buffer (read from OVL_L0_ADDR — the same buffer the - * menu was displayed from, and the one clear_screen() blackened at - * handoff). No parse result is needed to find it. Format: one row per - * u32 word, 32 cells of 32x32 px, MSB first, white=1 / black=0, rows - * every 64 px. Photograph the panel; decode offline. Word 0 is the - * marker 0xC0DE00xx identifying the failure stage. + * The parse failed. Paint the failing values as giant hex digits directly + * into the live scanout buffer (read from OVL_L0_ADDR — the same buffer + * the menu was displayed from and clear_screen() blackened at handoff). + * No parse result is needed to find it. One word per line, 8 digits of + * 3x5 cells scaled x10 (30x50 px), MSB nibble first, white on the black + * background depthcharge left. Readable in any panel orientation. + * Line 0 is the marker 0xC0DE00xx identifying the failure stage. */ #define DIAG_FB_WIDTH 1200 /* menu geometry, 32bpp xRGB */ +#define DIAG_DIGIT_SCALE 10 /* 3x5 font -> 30x50 px */ + +static const u16 hexfont[16] = { + 0b111101101101111, /* 0 */ + 0b010110010010111, /* 1 */ + 0b111001111100111, /* 2 */ + 0b111001011001111, /* 3 */ + 0b101101111001001, /* 4 */ + 0b111100111001111, /* 5 */ + 0b111100111101111, /* 6 */ + 0b111001001010010, /* 7 */ + 0b111101111101111, /* 8 */ + 0b111101111001111, /* 9 */ + 0b111101111101101, /* A */ + 0b100100111101111, /* b */ + 0b111100100100111, /* C */ + 0b001001111101111, /* d */ + 0b111100111100111, /* E */ + 0b111100111100100, /* F */ +}; + +static void fill_rect(u32 base, u32 x, u32 y, u32 w, u32 h, u32 c) +{ + volatile u32 *fb = (volatile u32 *)(u64)base; + for (u32 yy = 0; yy < h; yy++) { + volatile u32 *row = fb + (u64)(y + yy) * DIAG_FB_WIDTH + x; + for (u32 xx = 0; xx < w; xx++) + row[xx] = c; + } +} static void render_diag(u32 base, const u32 *d, int n) { - volatile u32 *fb = (volatile u32 *)(u64)base; + const u32 S = DIAG_DIGIT_SCALE; for (int i = 0; i < n; i++) { - u32 y0 = 40 + (u32)i * 64; - if (y0 + 32 > 1920) + u32 y0 = 30 + (u32)i * 70; + if (y0 + 50 > 1920) break; - for (u32 b = 0; b < 32; b++) { - u32 c = ((d[i] >> (31 - b)) & 1) ? 0x00FFFFFFu - : 0x00000000u; - for (u32 yy = 0; yy < 32; yy++) { - volatile u32 *row = fb + - (u64)(y0 + yy) * DIAG_FB_WIDTH + b * 32; - for (u32 xx = 0; xx < 32; xx++) - row[xx] = c; - } + for (u32 j = 0; j < 8; j++) { + u32 nib = (d[i] >> (28 - 4 * j)) & 0xF; + u16 g = hexfont[nib]; + u32 x0 = 40 + j * 4 * S; + for (u32 gy = 0; gy < 5; gy++) + for (u32 gx = 0; gx < 3; gx++) + if ((g >> (14 - gy * 3 - gx)) & 1) + fill_rect(base, + x0 + gx * S, + y0 + gy * S, + S, S, 0x00FFFFFFu); } } } @@ -363,9 +395,6 @@ static void fail_dump(u32 marker, const u32 *words, int n) render_diag(l0, diag, 16); halt(); } - -/* ---- main checkpoint sequence ------------------------------------------- */ - static void checkpoint(const struct fbinfo *f, int r, int g, int b) { fill_screen(f, mkcolor(f, r, g, b));