B1: a boot area on the disk, reserved by arithmetic that was already there

The first rung of booting from disk. A boot area is blocks between the
superblock and the directory that the filesystem never allocates and never
sees, and NOTHING WAS ADDED TO RESERVE THEM: both implementations work out
the first usable block as directoryStart + directoryBlocks, and
directoryStart has always been a field rather than a constant. Formatting
with the directory moved up reserves everything below it. Neither allocator
changed, on either side.

Two new superblock fields in bytes that were reserved: bootBlocks at 14,
per slot, and bootSlot at 16. A disk made before this has zero in both,
which reads as "no boot area" - true, and the same shape as the version two
parent field, where the value an older disk already held was the right
answer without conversion.

TWO SLOTS, ALWAYS. A boot slot is raw blocks with no entry to rename, so
the write-a-temporary-and-rename ordering that protects every file cannot
protect it, and a machine interrupted while updating its only slot would
not boot at all - the one failure on this disk with no way back. Writing
the slot that is not live and then moving one byte makes that a machine
that boots what it had before.

bootBlocks and directoryStart say the same thing from two sides, so a disk
where they disagree is refused rather than guessed at, as is one naming a
slot that does not exist.

Checked where it matters: the HOST formats a disk with a boot area and the
MACHINE fills it, then the reserved blocks are compared against zero. The
machine's allocator is the one that had no idea any of this was happening,
which is what makes that the check worth having. Six host checks besides,
including both halves of the superblock disagreeing.
This commit is contained in:
Anachronaut
2026-08-26 22:58:45 -04:00
parent 0a2965bc63
commit 612bd1b97c
5 changed files with 162 additions and 9 deletions
+35
View File
@@ -272,6 +272,41 @@ else
report FAIL "the machine sees it too" "dir showed it as an ordinary file"
fi
# ---- A boot area is blocks neither of them will touch ----
#
# Blocks between the superblock and the directory, reserved by moving the directory up
# rather than by anything new: both implementations work out the first usable block as
# directoryStart + directoryBlocks, and directoryStart has always been a field. So this
# checks a claim that no code was written to make true - which is exactly the kind most
# worth checking.
#
# The host formats it and the MACHINE fills it, because the machine's allocator is the one
# that had no idea any of this was happening.
"$TOOL" format bootarea.img 512 4 32 >/dev/null
"$TOOL" mkdir bootarea.img /Apps >/dev/null
"$TOOL" put bootarea.img Files.sbx /Apps/Files.sbx >/dev/null
printf 'Files\nFiles\nexit\n' \
| "$EMU" cosmos.bin --fast --disk bootarea.img > bootarea.txt 2>&1
if python3 - bootarea.img <<'CHECK'
import sys
image = open(sys.argv[1], "rb").read()
first = int.from_bytes(image[8:10], "big")
boot = image[256:first * 256]
sys.exit(0 if boot == bytes(len(boot)) else 1)
CHECK
then
report ok "the boot area is left alone" "the machine allocated around it"
else
report FAIL "the boot area is left alone" "something wrote into the reserved blocks"
fi
if "$TOOL" list bootarea.img | grep -q "kept.txt\|1 file\|0 files"; then
report ok "and the disk still works" "the host reads what the machine wrote"
else
report FAIL "and the disk still works" "the host could not read it back"
fi
# ---- And each can read what the other wrote ----
#
# Matching bytes and being readable are not the same claim. A field both of them write
+20
View File
@@ -172,6 +172,26 @@ check "the largest that fits" "$TOOL" format huge.img 65535 8191
printf '\x20\x00' | dd of=lying.img bs=1 seek=10 conv=notrunc status=none
refuses "nor reading one that claims it" "$TOOL" list lying.img
# ---- A boot area, and the two halves of the superblock that describe it ----
#
# bootBlocks and directoryStart say the same thing from two sides, so a disk where they
# disagree is one where there is no way to tell which is wrong. Both are refused.
check "format with a boot area" "$TOOL" format boot.img 512 4 32
check "and it reads back" "$TOOL" list boot.img
refuses "no boot area bigger than a disk" "$TOOL" format small.img 32 2 64
check "and none at all is still fine" "$TOOL" format plain.img 64 2
bootField() { python3 -c "
import sys
f = open(sys.argv[1], 'r+b'); f.seek(int(sys.argv[2])); f.write(bytes.fromhex(sys.argv[3]))
" "$@"; }
cp boot.img lying.boot.img
bootField lying.boot.img 14 0010 # Claims 16 blocks a slot, directory says 32.
refuses "nor a boot area that disagrees" "$TOOL" list lying.boot.img
cp boot.img badslot.img
bootField badslot.img 16 07 # Names slot 7, and there are two.
refuses "nor a slot that does not exist" "$TOOL" list badslot.img
echo
if [ "$FAIL" -eq 0 ]; then
echo "All $PASS disk tool checks passed."