B4: the disk remembers whether the last start arrived

The loader marks the superblock before it hands over and the system clears
the mark when it reaches its prompt, so a system that crashes on the way
there leaves it set. The loader finding it still set next time is how a
machine that will not start says so to the only thing in a position to do
anything about it. Without that, pointing boot.cfg at something that dies
before the shell is a machine that can never be told anything again - the
shell is the only way to change the file, and the file is what stops the
shell from starting.

Three states rather than two, and the third is the one worth having:

  0 settled    the last start arrived; use the configuration
  1 trying     handed over, and nothing came back to say it got there
  2 fell back  a try failed and the fallback was used, until settled

With only 0 and 1 the machine alternates for ever: fall back, reach a
prompt, clear the mark, retry the broken system, crash, fall back. State 2
stops that. A system known not to start is not tried again until somebody
says the situation has changed.

REACHING THE PROMPT IS A DELIBERATE THRESHOLD. It is not a claim that the
system works - a shell can be reached by something broken in every other
way. It is the point where a person can type, which is exactly what the
fallback exists to give back: anything wrong past there is fixable from the
prompt and nothing wrong before it is fixable at all.

The routines live in sbfs.asm because both the loader and the system read
and write this byte, and two pieces of code with their own idea of where a
byte lives is what this format has two implementations and a byte for byte
comparison to avoid.

And the trap this system documents in its own manual caught me anyway: the
first version handed the state back in A, which CALL restores, so every
read got whatever the caller happened to be holding. It comes back in
memory now, and the comment says why.

Three disks differing only in the state on them, so the tests read as three
consecutive starts of one machine while none depends on another running.
This commit is contained in:
Anachronaut
2026-08-27 16:51:39 -04:00
parent 546f336823
commit dc74149321
14 changed files with 368 additions and 3 deletions
+38
View File
@@ -268,6 +268,7 @@ increment, decrement, addition, and subtraction when their inputs are known.
| Command | What it does |
| --- | --- |
| `boot <image> <file> [slot]` | Write a file into a boot slot, padding the rest of it with zeroes. Slot 0 unless told otherwise. |
| `bootstate <image> [0\|1\|2]` | Show how the last start went, or set it. Setting it to 0 is how a disk that fell back is told to try again. |
| `bootslot <image> <slot>` | Choose which slot the machine starts from. One byte, on its own, so writing a slot and committing to it stay separate decisions. |
| `format <image> [blocks] [dirblocks] [bootblocks]` | Lay down a fresh filesystem. 512 blocks and 8 of directory by default, which is 128K and room for 64 entries. A fourth number reserves a boot area of two slots that size. |
| `list <image> [path]` | Show the whole disk, or one directory of it. |
@@ -295,6 +296,43 @@ so a machine interrupted while updating its only boot 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 in the superblock turns that into a machine that boots what it had before.
### Knowing Whether The Last Start Arrived:
The loader marks the disk before it hands over, and the system clears the mark when it
reaches its prompt. **A system that crashes on the way there leaves the mark**, and the
loader finding it still set next time is how a machine that will not start says so to the
only thing in a position to do anything about it.
| State | Means |
| -- | -- |
| 0 | Settled. The last start arrived, so start what the configuration says. |
| 1 | Trying. The loader handed over and nothing came back to say it got there. |
| 2 | Fell back. A try failed and the fallback was used, and will be until this is settled. |
Three starts of a machine whose configuration names something broken:
```
stage two
a system that never reaches a prompt <- marks the disk, dies
stage two
the last start did not arrive <- finds the mark, uses the fallback
CosmOS
this is the fallback: what boot.cfg asks for did not start
stage two
still on the fallback: settle it to try again <- does NOT retry
```
That third one is the part worth having. A system known not to start is not tried every
other boot for ever; it waits to be told the situation has changed.
**Reaching the prompt is a deliberate choice of threshold.** It is not a claim that the
system works - a shell can be reached by something broken in every other way. It is the
point where somebody can type, which is exactly what the fallback exists to give back:
anything wrong past there can be fixed from the prompt, and nothing wrong before it can be
fixed at all.
`bootBlocks` and `directoryStart` describe the same fact from two sides, so a disk where
they disagree is refused rather than guessed at.