Configuration files, and boot.cfg as the first of them
One setting to a line: a key, a space, the rest of the line is the value. A semicolon starts a comment. The format was noticed rather than designed - textSplit already cuts the first word off a line and leaves the rest, and textSame already insists two strings end together, so reading a setting is those two routines and a loop. It is also what the shell reads, which makes a configuration line a command line the machine reads instead of a person typing one. The format was chosen by asking what the BOOT LOADER could manage, because it is the worst case in every direction: a few kilobytes, no operating system to report to, and if it fails the machine does not start. Two formats would be worse than one and the loader cannot have the richer one. CONFIGURATION IS ADVICE. A missing file, a missing key, an unusable value, a line too long to read: all of them mean use the default and none is a failure. BUT QUIET IS NOT SILENT - a setting somebody meant, which did not take effect, says so. That was the user's addition and it is the better rule: the default alone leaves the only symptom being that the machine did not do what somebody asked. So two routines. cfgGet reads and says nothing, because reading three settings should not report one bad line three times. cfgCheck reads the file once and reports, and is handed the caller's list of keys - whether a key means anything is the only part of this a shared reader cannot judge. /System/Boot/ holds the boot files, and stage two reads boot.cfg for what to start, with a fallback to try if it does not work and a name compiled in for when the file says nothing. THE TEST FOUND A REAL BUG, and it is the interaction I would not have thought to look for. First-match-wins met an empty value: a file with system system /System/Boot/bare.bin matched the first line, handed back nothing, and the machine tried to start a file with no name while a good setting sat underneath. An unusable value is an absent one - which is what "configuration is advice" says, and this is where it earns its keep. cfgBare starts an image with no operating system in it at all, which is what loading an ordinary boot image buys: a program wanting the whole machine is a file like any other, chosen the same way the system is. Three disks differing ONLY in boot.cfg, so each is a test of the file rather than of the machinery under it.
This commit is contained in:
@@ -306,8 +306,8 @@ has versions - all of that lives in the boot area, on the disk, where it can be
|
||||
It reads the live slot into Program Memory, jumps to the first byte, and prints one
|
||||
character and stops if there is nothing to start.
|
||||
|
||||
`Programs/Boot/stage2.asm` is what sits in the slot. It mounts the filesystem, finds the
|
||||
system by name, and takes the image apart: code into Program Memory, data into Data
|
||||
`Programs/Boot/stage2.asm` is what sits in the slot. It mounts the filesystem, reads
|
||||
`/System/Boot/boot.cfg` to find out what to start, and takes the image apart: code into Program Memory, data into Data
|
||||
Memory, and each vector written through the controller, which is the only thing that can
|
||||
write Program Memory at all. The entry point is noticed on the boot vector's way past,
|
||||
because Program Memory cannot be read back to look it up afterwards.
|
||||
@@ -318,6 +318,53 @@ normal image format is not a boot-specific mechanism, so **bare metal SplitBit s
|
||||
a special case.** A program that wants no operating system under it is just an image,
|
||||
written under CosmOS like any other, and startable because it is a file.
|
||||
|
||||
### Configuration:
|
||||
|
||||
One setting to a line: a key, a space, and the rest of the line is the value. A semicolon
|
||||
starts a comment and a blank line is nothing.
|
||||
|
||||
```
|
||||
; /System/Boot/boot.cfg
|
||||
system /System/Boot/cosmos.bin
|
||||
fallback /System/Boot/cosmos-previous.bin
|
||||
```
|
||||
|
||||
That format was noticed rather than designed. `textSplit` already cuts the first word off a
|
||||
line and leaves the rest; `textSame` already compares two strings and insists they end
|
||||
together, so `system` and `systemd` are different words. Reading a setting is those two
|
||||
routines and a loop - and it is the shape the shell already reads, so **a configuration
|
||||
line is a command line the machine reads instead of a person typing one.**
|
||||
|
||||
**Configuration is advice.** A missing file, a missing key, a value that makes no sense, a
|
||||
line too long to read: all of them mean *use the default*, and none of them is a failure. A
|
||||
program that cannot run without its configuration has turned its configuration into a
|
||||
single point of failure, and for the thing that starts the machine that would mean a
|
||||
mistyped file is a machine that will not start.
|
||||
|
||||
**But quiet is not silent.** A setting somebody meant, which did not take effect, says so:
|
||||
|
||||
```
|
||||
a setting nothing asked for: fallbcak
|
||||
a setting with no value: system
|
||||
a line too long to read: ...
|
||||
```
|
||||
|
||||
So `config.asm` has two routines rather than one. `cfgGet` reads and never says anything -
|
||||
reading three settings should not report the same bad line three times. `cfgCheck` reads
|
||||
the file once and reports what it did not understand, and is given the caller's list of
|
||||
keys, because whether a key means anything is the only part of this the reader cannot
|
||||
judge for itself.
|
||||
|
||||
Keys are matched exactly and case sensitively, the first line that matches wins, and
|
||||
unknown keys are ignored rather than refused - so a file written by a newer system loses
|
||||
the settings an older one never had and keeps the ones it did. A line is at most 128 bytes
|
||||
and a key at most 22, which is what a name is everywhere else on this machine.
|
||||
|
||||
Deliberately absent: sections, nesting, types, includes, substitution, conditions. Each is
|
||||
a step from reading a file toward running one, and the boot loader is the worst place on
|
||||
this machine to put an interpreter. The test to apply when the pressure arrives is: **if
|
||||
this file cannot be read, can the machine still start?**
|
||||
|
||||
Stage two arranges its own Data Segment. Stage one places Program Memory and nothing else,
|
||||
since knowing where a payload's data ended would mean knowing a format, so the image is
|
||||
written into the slot as code followed by data and stage two's first act is to blit its
|
||||
|
||||
Reference in New Issue
Block a user