stub: render failure dump as giant hex digits

Round 8: the Round-7 bit-band dump was visible at the L0_ADDR scanout
(both the scanout substitution and the render path work), but 32 coarse
squares per row proved unreadable from a photo. Replace the rendering
with giant hex digits: one u32 per line, 8 digits of a 3x5 font scaled
x10 (30x50 px), white on the black background depthcharge left.
Readable in any panel orientation, transcribable as text.

Same data and markers as before; word 15 still carries the raw
OVL_L0_ADDR value. Payload 10760e3c... flashed and verified.
This commit is contained in:
vhaudiquet
2026-08-30 00:22:09 +02:00
parent 0974367f8d
commit edb21f2e94
4 changed files with 66 additions and 22 deletions
+15
View File
@@ -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`.
Binary file not shown.
BIN
View File
Binary file not shown.
+51 -22
View File
@@ -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));