diff options
| author | Bradley Morgan <brads@mainlining.org> | 2026-10-04 00:32:49 +0000 |
|---|---|---|
| committer | Bradley Morgan <brads@mainlining.org> | 2026-10-04 00:32:49 +0000 |
| commit | d72c2f898ed4c17aba0080c8bf6a0173cca940dc (patch) | |
| tree | 7ecfd6d2b7095e61e3ce7a5ee35a8772822ca6a8 /tools | |
| parent | 4f700c280b55c551047c00c71ef14aacf5830872 (diff) | |
tashaboot: image header, EL split, self located load address
qemu -kernel parses a raw arm64 blob as a linux Image and enters
at RAMBASE plus whatever text_offset it guesses out of the
garbage, 0x80000 in our case. every wild PC at image+0x80000 in
the debug logs was our own code running from the wrong address.
the binary now carries a real Image header: code0 branches over
it, magic ARM\x64 at 0x38, text_offset 0, image_size stamped
after objcopy by tools/fillsize.py.
the runtime also split by exception level. the C body runs at
EL1, the semihosting hlt is answered by qemu only from EL2, so
the EL2 vector replays the trap there and erets home with the
result. the kernel handoff hvc raises back to EL2 where
booting.rst wants it, the same vector slot dispatches PSCI hvc
from the kernel, boot handoff and semihosting by EC and function
id.
the payload load address was hardcoded 0x40200000, which is where
qemu placed our image, so the load overwrote the running
bootloader with kernel bytes mid flight. the load address is now
__image_copy_end plus 16MB, wherever the image actually runs.
receipt: run /init, tashaboot linux userspace reached, cores: 4,
busybox shell on a 4 cpu virt machine with initrd.
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/fillsize.py | 13 |
1 files changed, 13 insertions, 0 deletions
diff --git a/tools/fillsize.py b/tools/fillsize.py new file mode 100644 index 0000000..fa472d1 --- /dev/null +++ b/tools/fillsize.py @@ -0,0 +1,13 @@ +#!/usr/bin/env python3 +# fillsize.py - stamp image_size into the arm64 Image header of a +# built binary. the linker cannot know the final file size, the +# header field stays 0 through the link, this runs after objcopy. +import struct +import sys + +path = sys.argv[1] +d = bytearray(open(path, 'rb').read()) +assert d[0x38:0x3c] == b'ARM\x64', 'no Image magic, refusing to stamp' +struct.pack_into('<Q', d, 0x10, len(d)) +open(path, 'wb').write(d) +print('image_size %d stamped' % len(d)) |
