| git.druid.rocks | index | druid520 | kaboom | mk/ | bl.sh |
mk/bl.sh
#!/bin/sh
# assembles src/boot/dynamite.s into a real 512-byte boot sector, and
# extracts a raw flat binary of out/kaboom.elf for it to load -- the
# two artifacts mk/disk.pl embeds at lba 0 and lba 1-1024 respectively
# for the real bios-boot path (see mk/rb.sh). depends on out/kaboom.elf
# already existing (run mk/b.sh first); mk/ba.sh runs this in the
# right order.
. ./mk.conf
set -e
# _start's real, current runtime address, the blob's real load address
# and the blob's real size -- all read straight off the actual build,
# never hand-computed or hardcoded, so dynamite always copies the blob
# to where it was linked and jumps to wherever _start actually is on
# this exact build, not a guessed offset. the load address is the
# lowest LOAD segment's physical address: objcopy -O binary starts the
# blob at the lowest loadable section's lma, which is that same
# address.
entry=$("$readelf" -h "$out/kaboom.elf" | awk '/Entry point address/ {print $NF}')
loadaddr=$("$readelf" -lW "$out/kaboom.elf" | awk '$1 == "LOAD" {print $4}' | sort | head -n 1)
"$objcopy" -O binary "$out/kaboom.elf" "$out/kaboom.bin"
blobsize=$(wc -c < "$out/kaboom.bin")
dwords=$(( (blobsize + 3) / 4 ))
# dynamite.s's own read_loop reads a hardcoded 1024 sectors (512kib)
# off disk for the kernel blob, independent of KERNEL_BLOB_DWORDS --
# that dword count only drives the later rep movsl relocation, so a
# blob that outgrew 1024 sectors would silently have its tail truncated
# by the read itself, then dynamite would relocate/jump into whatever
# garbage happened to follow in the scratch buffer, with no error of
# any kind. catch it here instead, while there's still a real blobsize
# to check against.
if [ "$blobsize" -gt 524288 ]; then
echo "err: kaboom.bin is $blobsize bytes, past dynamite.s's 1024-sector (524288-byte) raw read limit -- grow read_loop's sector count (and disk.pl's matching layout) before this will boot." >&2
exit 1
fi
"$as" --32 --fatal-warnings "$src/boot/dynamite.s" -o "$out/dynamite.o" \
--defsym KERNEL_ENTRY_ADDR="$entry" --defsym KERNEL_LOAD_ADDR="$loadaddr" --defsym KERNEL_BLOB_DWORDS="$dwords"
# link to a real elf first (kept around for objdump/gdb), then pull
# out .text alone as the flat sector. linking straight to
# --oformat=binary was tried first and produced a 134mb file: gas
# emits a .note.gnu.property section by default, and ld's default
# script places it up near 0x8048000, so the flat output "spans" from
# 0x7c00 all the way up there. -j .text keeps only the real sector.
"$ld" -m elf_i386 -Ttext=0x7c00 -e _dynamite_start "$out/dynamite.o" -o "$out/dynamite.elf"
"$objcopy" -O binary -j .text "$out/dynamite.elf" "$out/dynamite.bin"
size=$(wc -c < "$out/dynamite.bin")
if [ "$size" -ne 512 ]; then
echo "err: dynamite.bin is $size bytes, must be exactly 512 (check .org 510 padding and whether the code itself overflowed into the signature)." >&2
exit 1
fi
echo "built $out/dynamite.bin (512 bytes) and $out/kaboom.bin ($blobsize bytes, $dwords dwords, load $loadaddr, entry $entry)"