<feed xmlns='http://www.w3.org/2005/Atom'>
<title>tashaboot/common/dtb_patch.c, branch main</title>
<subtitle>tashaboot multi-stage bootloader framework</subtitle>
<id>https://p10-linux-brads.osuosl.org/tashaboot/atom?h=main</id>
<link rel='self' href='https://p10-linux-brads.osuosl.org/tashaboot/atom?h=main'/>
<link rel='alternate' type='text/html' href='https://p10-linux-brads.osuosl.org/tashaboot/'/>
<updated>2026-10-04T00:32:49Z</updated>
<entry>
<title>tashaboot: image header, EL split, self located load address</title>
<updated>2026-10-04T00:32:49Z</updated>
<author>
<name>Bradley Morgan</name>
<email>brads@mainlining.org</email>
</author>
<published>2026-10-04T00:32:49Z</published>
<link rel='alternate' type='text/html' href='https://p10-linux-brads.osuosl.org/tashaboot/commit/?id=d72c2f898ed4c17aba0080c8bf6a0173cca940dc'/>
<id>urn:sha1:d72c2f898ed4c17aba0080c8bf6a0173cca940dc</id>
<content type='text'>
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.
</content>
</entry>
<entry>
<title>tashaboot: smp, psci, initrd, timer, cache by va</title>
<updated>2026-10-03T22:58:47Z</updated>
<author>
<name>Bradley Morgan</name>
<email>brads@mainlining.org</email>
</author>
<published>2026-10-03T22:58:47Z</published>
<link rel='alternate' type='text/html' href='https://p10-linux-brads.osuosl.org/tashaboot/commit/?id=61af8d6209b395a03ceab156b6df6720d638048e'/>
<id>urn:sha1:61af8d6209b395a03ceab156b6df6720d638048e</id>
<content type='text'>
The bootloader now does the whole job of machine firmware it owns:
boots 4 cpus, hands over an initrd, answers PSCI, and carries the
delay and cache primitives the arch layer needs.

SMP: the secondary pen is the Wait For Event mechanism from the
manual (B2-144, D1-2255), each secondary watches its spin gate,
WFE, the release writes the entry and SEVs, the recheck after each
wake covers a release that lands between the load and the sleep.
The gates land in the dtb cpu-release-addr slots, rewritten in
place by a small walker, no libfdt, structure per the devicetree
specification, values only, the properties themselves are fixed at
build time like firmware shipping a fixed blob.

PSCI 0.2 at EL2 (DEN 0022): the HVC trap arrives at the current EL
SP_ELx sync slot (EC 0x16 in ESR_EL2, the vector layout Table D1-7),
dispatch on the standard function ids, VERSION, CPU_ON writes the
target gate and SEVs, CPU_OFF clears the gate and returns to the
pen, SYSTEM_OFF and SYSTEM_RESET drive RMR_EL2.RR. On qemu the cores
are held by the machine's own firmware and released through its PSCI
(hvc with -kernel, smc with virtualization=on), the handler here is
the real hardware path where the bootloader is the conduit.

The initrd handoff: loaded at a fixed address clear of the image
and dtb, the dtb /chosen carries linux,initrd-start and -end.

Delays are the generic timer (D10), CNTFRQ_EL0 frequency, CNTVCT_EL0
count, busy wait, no interrupts. Cache maintenance by virtual
address, dc cvac, dc ivac, dc civac, ic ivau with the barrier pairs
the manual requires, the by VA form beats set and way when the
range is known.

Boot receipt, 4 cpus, el2, initrd:

  tashaboot 0.1
  initrd at 46000000
  [    0.000000] Booting Linux on physical CPU 0x0000000000
  [    0.130621] smp: Brought up 1 node, 4 CPUs
  [    1.830692] Run /init as init process
  tashaboot linux userspace reached
  cores: 4
  BusyBox v1.37.0 built-in shell (ash)
  ~ #

Signed-off-by: Bradley Morgan &lt;brads@mainlining.org&gt;
</content>
</entry>
</feed>
