diff --git a/RESEARCH.md b/RESEARCH.md index a3dc9b4..c211d85 100644 --- a/RESEARCH.md +++ b/RESEARCH.md @@ -734,3 +734,53 @@ zeros to 0x1000 + NO U-Boot, tail branch patched to self (hang): |---|---| | magenta + blinks + hang | interior pad innocent; the trigger is U-Boot content/placement at 0x1000 | | black, nothing | depthcharge rejects the padded image before any execution | + +## Round 19 — Test B decoded: wrapper runs in padded layout; correct PIE alignment + post-clear checkpoint + +Test B (`9485c59e…`): **wrapper color + 3 blinks + color held** — the +wrapper runs fine even in the padded/0x1000 layout, with NO U-Boot +present. Depthcharge is fully exonerated: it copies and jumps every +payload. Combined with R14/R15 (black), the story closes: U-Boot (at +0x1000, aligned) RAN in R14/R15, reached the video probe and its +`video_clear()` (black over the wrapper color, backlight back on), and +died somewhere between the clear and a visible banner. The user's +"no backlight" was a backlit-black misread (matches R5's physics). +(The R15 blink train was evidently too brief to register.) + +### Alignment math corrected ([REVERSED] earlier notes) + +The U-Boot file does NOT start at _start: a 4-byte stub precedes it +(nm: link _start = CONFIG_TEXT_BASE + 4). Two constraints must hold +simultaneously: +1. start.S wfi check: runtime _start ≡ 0 (mod 4K); +2. PIE fixup (adrp+add lo12): runtime _start ≡ link _start (mod 4K). +⇒ link _start must be 4K-aligned: CONFIG_TEXT_BASE=0x4C000FFC → link +_start=0x4C001000; U-Boot file placed at image offset 0xEC0 → runtime +_start=0x40001000. Verified: nm shows 0x4c001000; the payload script +now asserts it against u-boot.sym. (Earlier R14/R15 layouts had runtime +_start page offset 0x40 → wfi-hang — but green should have persisted; +the observed black is only explained by the video_clear path, which +means R14's U-Boot PASSED the wfi check... [OPEN] the R14/R15 images +had link _start=0x4C000140 (page offset 0x140) and runtime 0x1040 +(0x40) — mismatched mod 4K by 0x100, so even past the wfi check the PIE +fixup would corrupt pointers; either way the video_clear observation +stands as the only black-producing mechanism.) + +### Round 19 payload (`1f598c7a…`, flashed, cmp+vbutil OK) + +- CONFIG_TEXT_BASE=0x4C000FFC, U-Boot file at image 0xEC0 (correct + alignment for both constraints); +- new checkpoint: WHITE band painted at the END of video_post_probe + (after the vidconsole child is bound+probed) — post-clear deaths are + now distinguishable from banner-stage deaths; +- all earlier checkpoints retained (orange/blue/red bands, misc_init_r + yellow). + +### Decision tree + +| observation | meaning | +|---|---| +| magenta + blinks + magenta persists | U-Boot died BEFORE the video probe (bands show how far) | +| black + white band | video probe completed; died between post_probe and banner | +| black, no white band | died inside video_post_probe after video_clear (bind/probe of vidconsole) | +| banner (white on black) | works | diff --git a/build-uboot-payload.sh b/build-uboot-payload.sh index 0432cda..b5465de 100755 --- a/build-uboot-payload.sh +++ b/build-uboot-payload.sh @@ -38,21 +38,27 @@ uboot = open(uboot_path, 'rb').read() wrapper = open('uboot-wrapper.bin', 'rb').read() assert len(wrapper) == wrap_len -# wrapper entry at 0x40, U-Boot right after the wrapper (contiguous) +# (layout comment continues) +# U-Boot's file has a 4-byte stub before _start (link _start = +# CONFIG_TEXT_BASE + 4). With CONFIG_TEXT_BASE=0x4C000FFC link _start = +# 0x4C001000 (4K-aligned); placing the file at image offset 0xEC0 puts +# runtime _start at 0x40001000: the wfi alignment check passes and the +# PIE fixup delta stays 4K-aligned. wrap_off = 0x40 -uboot_off = wrap_off + wrap_len +uboot_off = 0xEC0 +pad = uboot_off - wrap_off - wrap_len total = uboot_off + len(uboot) # verify the U-Boot link address matches its runtime placement for line in open(sym_path): parts = line.split() - if len(parts) == 3 and parts[2] == '_start': + if len(parts) >= 2 and parts[-1] == '_start': start = int(parts[0], 16) break else: raise SystemExit('_start not found in u-boot.sym') -assert start == 0x4c000000 + uboot_off, \ - "TEXT_BASE/_start 0x%x != expected 0x%x" % (start, 0x4c000000 + uboot_off) +assert start == 0x4c001000, \ + "link _start 0x%x != expected 0x4c001000" % start hdr = bytearray(64) hdr[0:4] = struct.pack('> 2) | 0x14000000) # code0: b +0x40 @@ -69,6 +75,7 @@ wrapper[-4:] = struct.pack('