c312853f8effc78b8a90fc8e0047aa700010de4e
4
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
c312853f8e |
The machine starts itself
stage two CosmOS > saved it read it back, 22 bytes: Stage one hands over to stage two out of a boot slot; stage two mounts the filesystem, finds /System/cosmos.bin, takes the image apart and places its code, its data and its vector table, and jumps to the entry point the vectors named. Nothing placed memory for it. What it loads is an ORDINARY BOOT IMAGE, the same SPBT file the emulator has always been handed. That was the user's call and it is the whole trick: a second stage that loads the machine's normal image format is not a boot-specific mechanism, so bare metal SplitBit stops being a special case. A program wanting no operating system under it is just an image, written under CosmOS like any other, and startable because it is a file. Three things in it worth knowing: - THE ENTRY POINT IS CAUGHT ON ITS WAY PAST. Program Memory cannot be read back, so the boot vector cannot be looked up after being installed; the vector loop notices the one addressed at 0xFC00 and keeps it. - A missing "VEC" is not a fault. An image written before vectors existed simply ends after its data, and then the entry point is zero, which is what every such image has always relied on. - Feature flags that are set mean an image asking for a machine this may not be, and the honest answer to a request that cannot be understood is to refuse rather than to run it anyway. The test records that the system WORKS afterwards rather than that it started. A loaded program running is what says the vector table arrived, because a program reaches the system through SWI and nothing else; the file written and the directory entered say the filesystem and the console came up with it. A second disk has a boot slot and nothing to start, and says so rather than jumping somewhere. |
||
|
|
82adeeb193 |
A boot payload can arrange its own Data Segment
Stage one places Program Memory and nothing else, because knowing where a payload's data ends and its code begins would mean knowing a format, and knowing formats is what ROM must do as little of as possible. But the real second stage needs a Data Segment: sbfs.asm has variables and a string it compares against. The answer needs nothing new. A loadable image is written into the slot as code followed by data, so the data image is already in Program Memory just past the code - and the payload's first instructions blit it down to where it was assembled for. Proved by slotData.asm, which prints from a string it placed itself. The padding is the part worth recording. The blit needs a length and the assembler will not work out the difference between two labels, so the segment is padded to a round number and that number is what gets copied. The first draft padded to 257 and copied 256, and the byte that did not arrive was padding, so it worked by luck. It is exact now and says why. This is the shape the user asked for and it goes further than the mechanism: the second stage becomes a loader for the machine's ORDINARY image format rather than for anything boot-specific, so bare metal SplitBit stops being a special case. A program that wants no operating system is just an image, developed under CosmOS like any other, and selectable at boot because it is a file. |
||
|
|
d07b23f90b |
Rung 2: the machine starts itself off a disk
Stage one exists and works. It is 330 bytes of program and everything it knows is a thing that will be true forever: which port the disk is on, that a SplitBit disk begins with its own name, and where two numbers sit in that first block. Not what a file is, not what a directory is, not that SBFS has versions. It reads the live boot slot into Program Memory, jumps to the first byte, and prints one character and halts if there is nothing there. It is an ordinary boot image for now, so the whole chain runs on machinery that already exists and the emulator has not been touched. Nothing about it changes when it moves into ROM except who puts it in memory. SplitDisk gained "boot" to write a slot and "bootslot" to choose one, kept apart on purpose: writing a slot and starting from it are different decisions, and joining them would make every write a commitment. A slot is always written WHOLE, because one still holding the tail of what was there before is one whose contents depend on its history, and stage one reads all of it without knowing where the file stopped. Three recorded tests, and the pair is the point: two disks differing only in which slot the superblock names, with payloads that say different things. One prints "booted" and the other does not, so this is a test of CHOOSING a slot rather than a test that some bytes were read. The third boots a disk with no boot area and gets the one character a ROM has room for. Eight more host checks, including that a slot is padded whole. Two things worth recording. The first draft used #Align to put the scratch buffer at 0x8000 and produced a 33K file - thirty two kilobytes of zeroes in something meant to be a ROM. It is an address, not storage, which is exactly what the assembler's own scratch map exists to say. And SplitLint caught the second in code written an hour after the baseline that catches it. In the blit set-up, RSTA writes a source address of zero and then RSTA writes a bank number of zero - two unrelated quantities that are equal by accident, in the most safety critical file in the repository. It is marked with a reason rather than removed. |
||
|
|
0a2965bc63 |
Name the rules, say when there is nothing to say, and hold a baseline
Four things SplitLint wanted, and they build on each other. EVERY WARNING NAMES ITS RULE, in brackets at the end the way a compiler names the flag that produced it. Twelve rules, listed by --help. That makes the other three possible: suppressions can name one rule and leave the line honest about the others, the harness can assert on a rule's identity rather than on the wording of its message, and --machine can print one tab separated line per warning - file, line, rule, message, help - so nothing downstream reads prose. This file's own output was parsed with regular expressions three times in one day before it had a shape to rely on. A CLEAN RUN SAYS SO: No style warnings: 121 files checked against 12 rules. It used to exit in silence, which does not tell you it found nothing - it tells you nothing at all, and from outside the two are identical. A MARKER THAT SILENCES NOTHING IS ITSELF REPORTED, as dead-suppression. An exception that outlived whatever made it necessary is the thing the required reason exists to prevent, and naming the wrong rule now gets you both the warning you meant to silence and a note that your suppression is doing nothing. AND THE CORPUS IS HELD TO A BASELINE. Sixty one warnings are left in it deliberately and nothing stopped a sixty second. Tests/lint-baseline.txt records how many of each rule each file should produce, so a new one fails make test while the sixty one stay quiet; confirmed by adding an INIA 0d0 to Say.asm and watching it name the file, the rule and the count. It counts per file and rule rather than recording line numbers, because line numbers would churn the whole baseline whenever anything was inserted above a warning - the same reason cycle counts are stripped from recorded output here. ./Tests/lint.sh --bless records it again. One thing to know for next time: the rule name was inserted before the line number at all twenty one call sites, and the signature was changed to match rather than the twenty one call sites being fixed. (path, rule, line) reads no worse than (path, line, rule) and one edit has fewer ways to go wrong than twenty one. |