Round 19: correct PIE alignment (TEXT_BASE=0x4C000FFC, file@0xEC0) + post-clear checkpoint

This commit is contained in:
vhaudiquet
2026-08-30 13:26:40 +02:00
parent 391756e573
commit a74e465e2d
4 changed files with 62 additions and 5 deletions
+50
View File
@@ -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 |
+12 -5
View File
@@ -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('<I', (0x40 >> 2) | 0x14000000) # code0: b +0x40
@@ -69,6 +75,7 @@ wrapper[-4:] = struct.pack('<I', (imm & 0x03ffffff) | 0x14000000)
with open(out, 'wb') as f:
f.write(hdr)
f.write(wrapper)
f.write(bytes(pad))
f.write(uboot)
print("layout: header 64, wrapper %d (0x40..0x%x), uboot %d @0x%x, total %d" %
(wrap_len, uboot_off, len(uboot), uboot_off, total))
Binary file not shown.
BIN
View File
Binary file not shown.