Round 19: correct PIE alignment (TEXT_BASE=0x4C000FFC, file@0xEC0) + post-clear checkpoint
This commit is contained in:
+50
@@ -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
@@ -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.
Binary file not shown.
Reference in New Issue
Block a user