mirror of
https://github.com/hsoft/collapseos.git
synced 2024-11-01 13:10:57 +11:00
134 lines
4.8 KiB
Plaintext
134 lines
4.8 KiB
Plaintext
# Bootstrap guide
|
|
|
|
You want to deploy Collapse OS on a new system? Read usage.txt,
|
|
impl.txt, cross.txt, then continue here.
|
|
|
|
What is Collapse OS? It is a binary placed either in ROM on
|
|
in RAM by a bootloader. That binary, when executed, initializes
|
|
itself to a Forth interpreter. In most cases, that Forth
|
|
interpreter will have some access to a mass storage device,
|
|
which allows it to access Collapse OS' disk blocks and bootstrap
|
|
itself some more.
|
|
|
|
This binary can be separated in 5 distinct layers:
|
|
|
|
1. Arch-specific boot code (B280 for Z80)
|
|
2. Arch-specific boot words (B305 for Z80)
|
|
3. Arch-independant core words (low) (B350)
|
|
4. Drivers, might contain arch-specific code
|
|
5. Arch-independant core words (high) (B390)
|
|
|
|
# Boot code
|
|
|
|
This part contains core routines that underpins Forth fundamen-
|
|
tal structures: dict navigation and FIND, PSP/RSP bounds checks,
|
|
word types.
|
|
|
|
It also of course does core initialization: set RSP/PSP, HERE
|
|
CURRENT, then call BOOT.
|
|
|
|
It also contains what we call the "stable ABI" in its first
|
|
few (<0x20) bytes.
|
|
|
|
# Boot words
|
|
|
|
Then come the implementation of core Forth words in native
|
|
assembly. Performance is not Collapse OS' primary design goal,
|
|
so we try to keep this section to a minimum: we much prefer
|
|
to implement our words in Forth.
|
|
|
|
However, some words are in this section for performance
|
|
reasons. Sometimes, the gain is too great to pass up.
|
|
|
|
# Core words (low)
|
|
|
|
Then comes the part where we begin defining words in Forth.
|
|
Core words are designed to be cross-compiled (B260), from a
|
|
full Forth interpreter. This means that it has access to more
|
|
than boot words. This comes with tricky limitations.
|
|
|
|
See B260 for details.
|
|
|
|
# Drivers
|
|
|
|
Core words don't include (key) and (emit) implementations be-
|
|
cause that's hardware-dependant. This is where we need to load
|
|
code that implement it, as well as any other code we want to
|
|
include in the binary.
|
|
|
|
We do it now because if we wait until the high layer of core
|
|
words is loaded, we'll have messed up immediates and ":" will
|
|
be broken. If we load our code before, we won't have access to
|
|
a wide vocabulary.
|
|
|
|
# Core words (high)
|
|
|
|
The final layer of core words contains the BOOT word as well
|
|
as tricky immediates which, if they're defined sooner, mess
|
|
cross compilation up. Once this layer is loaded, we become
|
|
severly limited in the words we can use without messing up.
|
|
|
|
# Hook word
|
|
|
|
After having loaded that last core words layer, we end that
|
|
with a hook word, the "(entry) _" line. A hook word is an empty
|
|
word at the end of the dictionary which serves 3 purposes:
|
|
|
|
1. After having created that word, PC conveniently holds the
|
|
value that should go in the LATEST field in stable ABI. Had
|
|
the word been non-empty, getting that value would be less
|
|
straightforward.
|
|
2. Because LATEST points to an empty word, it means that it also
|
|
points to the initialization string, which directly follows.
|
|
If it was non-empty, we would need to know the word's length
|
|
to get to that string.
|
|
3. If, for some reason, you want to "graft" another dictionary
|
|
on top of this one, having it end with an empty word makes
|
|
grafting convenient: you already know what your "prev field"
|
|
offset should be for the grafting to be correct.
|
|
|
|
# Initialization string
|
|
|
|
After the last word of the dictionary comes the "source init"
|
|
part. The boot sequence is designed to interpret whatever comes
|
|
after LATEST as Forth source, and this, until it reads ASCII
|
|
EOT character (4). This is generally used for driver init.
|
|
|
|
# Building it
|
|
|
|
So that's the anatomy of a Collapse OS binary. How do you build
|
|
one? If your machine is already covered by a recipe, you're in
|
|
luck: follow instructions.
|
|
|
|
If you're deploying to a new machine, you'll have to write a
|
|
new xcomp (cross compilation) unit. Let's look at its
|
|
anatomy. First, we have constants. Some of them are device-
|
|
specific, but some of them are always there. SYSVARS is the
|
|
address at which the RAM starts on the system. System variables
|
|
will go there and use 0x80 bytes. See impl.txt.
|
|
|
|
HERESTART determines where... HERE is at startup. 0 means
|
|
"same as CURRENT".
|
|
|
|
RS_ADDR is where RSP starts and PS_ADDR is where PSP starts.
|
|
RSP and PSP are designed to be contiguous. RSP goes up and PSP
|
|
goes down. If they meet, we know we have a stack overflow.
|
|
|
|
Then, we load the assembler and cross compilation unit, which
|
|
will be needed for the task ahead.
|
|
|
|
Then, it's a matter of adding layer after layer. For most
|
|
system, all those layers except the drivers will be added the
|
|
same way. Drivers are a bit tricker and machine specific. I
|
|
can't help you there, you'll have to use your wits.
|
|
|
|
After we've loaded the high part of the core words, we're at
|
|
the "wrapping up" part. We add the hook word and init string.
|
|
|
|
To produce a Collapse OS binary, you run that xcomp unit and
|
|
then observe the values of "ORG @" and "H@". That will give you
|
|
the start and stop offset of your binary, which you can then
|
|
copy to your target media.
|
|
|
|
Good luck!
|