mirror of
https://github.com/hsoft/collapseos.git
synced 2024-12-24 14:28:06 +11:00
Add /tools/slatest
To update LATEST offset more easily. Will be useful for recipes.
This commit is contained in:
parent
6bf51ae57c
commit
9235fa9223
15
README.md
15
README.md
@ -19,6 +19,14 @@ manage to build and install Collapse OS without external resources (i.e.
|
||||
internet) on a machine of her design, built from scavenged parts with low-tech
|
||||
tools.
|
||||
|
||||
## Forth reboot in process
|
||||
|
||||
You are currently looking at the `forth` branch of the project, which is a
|
||||
Forth reboot of Collapse OS. You can see why I'm doing this in the [related
|
||||
github issue][forth-issue].
|
||||
|
||||
Documentation is lacking, it's not ready yet, this is a WIP branch.
|
||||
|
||||
## See it in action
|
||||
|
||||
Michael Schierl has put together [a set of emulators running in the browser that
|
||||
@ -29,8 +37,8 @@ path to giving Collapse OS a try.
|
||||
|
||||
## Organisation of this repository
|
||||
|
||||
* `kernel`: Pieces of code to be assembled by the user into a kernel.
|
||||
* `apps`: Pieces of code to be assembled into "userspace" application.
|
||||
* `forth`: Forth is slowly taking over this project (see issue #4). It comes
|
||||
from this folder.
|
||||
* `recipes`: collection of recipes that assemble parts together on a specific
|
||||
machine.
|
||||
* `doc`: User guide for when you've successfully installed Collapse OS.
|
||||
@ -39,8 +47,6 @@ path to giving Collapse OS a try.
|
||||
through a serial port.
|
||||
* `emul`: Emulated applications, such as zasm and the shell.
|
||||
* `tests`: Automated test suite for the whole project.
|
||||
* `forth`: Forth is slowly taking over this project (see issue #4). It comes
|
||||
from this folder.
|
||||
|
||||
## Status
|
||||
|
||||
@ -58,4 +64,5 @@ A more traditional [mailing list][listserv] and IRC (#collapseos on freenode) ch
|
||||
[jsemul]: https://schierlm.github.io/CollapseOS-Web-Emulator/
|
||||
[discussion]: https://www.reddit.com/r/collapseos
|
||||
[listserv]: http://lists.sonic.net/mailman/listinfo/collapseos
|
||||
[forth-issue]: https://github.com/hsoft/collapseos/issues/4
|
||||
|
||||
|
@ -1,36 +1,21 @@
|
||||
CFSPACK_OBJ = ../tools/cfspack/libcfs.o
|
||||
TARGETS = shell/shell zasm/zasm runbin/runbin forth/forth
|
||||
KERNEL = ../kernel
|
||||
APPS = ../apps
|
||||
ZASMBIN = zasm/zasm
|
||||
AVRABIN = zasm/avra
|
||||
SHELLAPPS = zasm ed
|
||||
SHELLTGTS = ${SHELLAPPS:%=cfsin/%}
|
||||
TARGETS = runbin/runbin forth/forth
|
||||
# Those Forth source files are in a particular order
|
||||
FORTHSRCS = core.fs str.fs parse.fs readln.fs fmt.fs z80a.fs
|
||||
FORTHSRC_PATHS = ${FORTHSRCS:%=../forth/%}
|
||||
CFSIN_CONTENTS = $(SHELLTGTS) cfsin/user.h
|
||||
OBJS = emul.o libz80/libz80.o
|
||||
SHELLOBJS = $(OBJS) $(CFSPACK_OBJ)
|
||||
ZASMOBJS = $(SHELLOBJS)
|
||||
SLATEST = ../tools/slatest
|
||||
|
||||
.PHONY: all
|
||||
all: $(TARGETS) $(AVRABIN) $(CFSIN_CONTENTS)
|
||||
all: $(TARGETS)
|
||||
|
||||
# -o in sync with SHELL_CODE in shell/glue.asm
|
||||
shell/shell.bin: shell/glue.asm $(ZASMBIN)
|
||||
$(ZASMBIN) $(KERNEL) shell/user.h $(APPS) < shell/glue.asm | tee $@ > /dev/null
|
||||
$(SLATEST):
|
||||
$(MAKE) -C ../tools
|
||||
|
||||
shell/shell-bin.h: shell/shell.bin
|
||||
./bin2c.sh KERNEL < shell/shell.bin | tee $@ > /dev/null
|
||||
|
||||
shell/shell: shell/shell.c $(SHELLOBJS) shell/shell-bin.h
|
||||
$(CC) shell/shell.c $(SHELLOBJS) -o $@
|
||||
|
||||
# z80c.bin is not in the prerequisites because its a bootstrap binary that
|
||||
# should be updated manually through make fbootstrap.
|
||||
forth/forth0.bin:
|
||||
# z80c.bin and boot.bin are not in the prerequisites because they're bootstrap
|
||||
# binaries that should be updated manually through make updatebootstrap.
|
||||
forth/forth0.bin: $(SLATEST)
|
||||
cat forth/boot.bin forth/z80c.bin > $@
|
||||
$(SLATEST) $@
|
||||
|
||||
forth/forth0-bin.h: forth/forth0.bin
|
||||
./bin2c.sh KERNEL < forth/forth0.bin | tee $@ > /dev/null
|
||||
@ -44,8 +29,9 @@ forth/stage1dbg: forth/stage.c $(OBJS) forth/forth0-bin.h
|
||||
forth/core.bin: $(FORTHSRC_PATHS) forth/stage1
|
||||
cat $(FORTHSRC_PATHS) ./forth/stop.fs | ./forth/stage1 | tee $@ > /dev/null
|
||||
|
||||
forth/forth1.bin: forth/forth0.bin forth/core.bin
|
||||
forth/forth1.bin: forth/forth0.bin forth/core.bin $(SLATEST)
|
||||
cat forth/forth0.bin forth/core.bin > $@
|
||||
$(SLATEST) $@
|
||||
|
||||
forth/forth1-bin.h: forth/forth1.bin
|
||||
./bin2c.sh KERNEL < forth/forth1.bin | tee $@ > /dev/null
|
||||
@ -56,24 +42,6 @@ forth/stage2: forth/stage.c $(OBJS) forth/forth1-bin.h
|
||||
forth/forth: forth/forth.c $(OBJS) forth/forth1-bin.h
|
||||
$(CC) forth/forth.c $(OBJS) -o $@
|
||||
|
||||
zasm/kernel-bin.h: zasm/kernel.bin
|
||||
./bin2c.sh KERNEL < zasm/kernel.bin | tee $@ > /dev/null
|
||||
|
||||
zasm/zasm-bin.h: zasm/zasm.bin
|
||||
./bin2c.sh USERSPACE < zasm/zasm.bin | tee $@ > /dev/null
|
||||
|
||||
$(ZASMBIN): zasm/zasm.c $(ZASMOBJS) zasm/kernel-bin.h zasm/zasm-bin.h
|
||||
$(CC) zasm/zasm.c $(ZASMOBJS) -o $@
|
||||
|
||||
zasm/avra.bin: $(ZASMBIN)
|
||||
$(ZASMBIN) $(KERNEL) $(APPS) zasm/user.h < $(APPS)/zasm/gluea.asm > $@
|
||||
|
||||
zasm/avra-bin.h: zasm/avra.bin
|
||||
./bin2c.sh USERSPACE < zasm/avra.bin | tee $@ > /dev/null
|
||||
|
||||
$(AVRABIN): zasm/zasm.c $(ZASMOBJS) zasm/kernel-bin.h zasm/avra-bin.h
|
||||
$(CC) -D AVRA zasm/zasm.c $(ZASMOBJS) -o $@
|
||||
|
||||
runbin/runbin: runbin/runbin.c $(OBJS)
|
||||
$(CC) runbin/runbin.c $(OBJS) -o $@
|
||||
|
||||
@ -84,28 +52,12 @@ libz80/libz80.o: libz80/z80.c
|
||||
emul.o: emul.c
|
||||
$(CC) -c -o emul.o emul.c
|
||||
|
||||
$(CFSPACK_OBJ): ${@:%.o=%.c}
|
||||
$(MAKE) -C ../tools/cfspack
|
||||
|
||||
# -o in sync with USER_CODE in shell/user.h
|
||||
$(SHELLTGTS): $(ZASMBIN)
|
||||
$(ZASMBIN) -o 42 $(KERNEL) $(APPS) shell/user.h < $(APPS)/${@:cfsin/%=%}/glue.asm > $@
|
||||
|
||||
cfsin/user.h: shell/user.h
|
||||
cp shell/user.h $@
|
||||
|
||||
.PHONY: updatebootstrap
|
||||
updatebootstrap: $(ZASMBIN)
|
||||
$(ZASMBIN) $(KERNEL) < zasm/glue.asm > zasm/kernel.bin
|
||||
$(ZASMBIN) $(KERNEL) $(APPS) zasm/user.h < $(APPS)/zasm/glue.asm > zasm/zasm.bin
|
||||
|
||||
# We need to double wrap around dummy.fs because at stage3, we have high-level
|
||||
# words and they write to HERE at initialization.
|
||||
.PHONY: fbootstrap
|
||||
fbootstrap: forth/stage2
|
||||
cat ./forth/conf.fs ../forth/boot.fs | ./forth/stage2 > forth/boot.bin
|
||||
updatebootstrap: forth/stage2
|
||||
cat ./forth/conf.fs ../forth/boot.fs | ./forth/stage2 | tee forth/boot.bin > /dev/null
|
||||
cat ./forth/conf.fs ../forth/z80c.fs forth/emul.fs ../forth/icore.fs | ./forth/stage2 | tee forth/z80c.bin > /dev/null
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -f $(TARGETS) $(SHELLTGTS) emul.o zasm/*-bin.h shell/*-bin.h
|
||||
rm -f $(TARGETS) emul.o forth/*-bin.h forth/forth?.bin
|
||||
|
@ -20,82 +20,20 @@ First, make sure that the `libz80` git submodule is checked out. If not, run
|
||||
|
||||
After that, you can run `make` and it builds all applications.
|
||||
|
||||
## shell
|
||||
|
||||
Running `shell/shell` runs the BASIC shell in an emulated machine. The goal of
|
||||
this machine is not to simulate real hardware, but rather to serve as a
|
||||
development platform. What we do here is we emulate the z80 part, the 64K
|
||||
memory space and then hook some fake I/Os to stdin, stdout and a small storage
|
||||
device that is suitable for Collapse OS's filesystem to run on.
|
||||
|
||||
Through that, it becomes easier to develop userspace applications for Collapse
|
||||
OS.
|
||||
|
||||
By default, the shell initialized itself with a CFS device containing the
|
||||
contents of `cfsin/` at launch (it's packed on the fly). You can specify an
|
||||
alternate CFS device file (it has to be packaed already) through the `-f` flag.
|
||||
|
||||
By default, the shell runs interactively, but you can also pipe contents through
|
||||
stdin instead. The contents will be interpreted exactly as if you had typed it
|
||||
yourself and the result will be spit in stdout (it includes your typed in
|
||||
contents because the Collapse OS console echoes back every character that is
|
||||
sent to it.). This feature is useful for automated tests in `tools/tests/shell`.
|
||||
|
||||
## zasm
|
||||
|
||||
`zasm/zasm` is `apps/zasm` wrapped in an emulator. It is quite central to the
|
||||
Collapse OS project because it's used to assemble everything, including itself!
|
||||
|
||||
The program takes no parameter. It reads source code from stdin and spits
|
||||
binary in stdout. It supports includes and had both `apps/` and `kernel` folder
|
||||
packed into a CFS that was statically included in the executable at compile
|
||||
time.
|
||||
|
||||
The file `zasm/zasm.bin` is a compiled binary for `apps/zasm/glue.asm` and
|
||||
`zasm/kernel.bin` is a compiled binary for `tools/emul/zasm/glue.asm`. It is
|
||||
used to bootstrap the assembling process so that no assembler other than zasm
|
||||
is required to build Collapse OS.
|
||||
|
||||
This binary is fed to libz80 to produce the `zasm/zasm` "modern" binary and
|
||||
once you have that, you can recreate `zasm/zasm.bin` and `zasm/kernel.bin`.
|
||||
|
||||
This is why it's included as a binary in the repo, but yes, it's redundant with
|
||||
the source code.
|
||||
|
||||
Those binaries can be updated with the `make updatebootstrap` command. If they
|
||||
are up-to date and that zasm isn't broken, this command should output the same
|
||||
binary as before.
|
||||
|
||||
## avra
|
||||
|
||||
In the `zasm` folder, there's also `avra` which is a zasm compiled as an AVR
|
||||
assembler. It works the same way as zasm except it expects AVR mnemonics and
|
||||
spits AVR binaries.
|
||||
|
||||
## runbin
|
||||
|
||||
This is a very simple tool that reads binary z80 code from stdin, loads it in
|
||||
memory starting at address 0 and then run the code until it halts. The exit
|
||||
code of the program is the value of `A` when the program halts.
|
||||
|
||||
This is used for unit tests.
|
||||
|
||||
## forth
|
||||
|
||||
Collapse OS' Forth interpreter, which will probably soon replace the whole OS.
|
||||
Collapse OS' Forth interpreter, which is in the process of replacing the
|
||||
zasm-based project.
|
||||
|
||||
At this point, it is not yet entirely self-hosting, but will be eventually.
|
||||
Because of that aim, it currently builds in a particular manner.
|
||||
The Forth interpreter is entirely self-hosting, that is, it assembles its
|
||||
binary with itself.
|
||||
|
||||
There are 3 build stages.
|
||||
|
||||
**Stage 0**: This stage is created with zasm by assembling `forth/forth.asm`
|
||||
and `z80c.bin` through `stage0.asm`. This yields `forth0.bin`. We then wrap
|
||||
this binary with `stage.c` to create the `stage1` binary, which allows us to
|
||||
get to the next stage.
|
||||
|
||||
`z80c.bin` is a "chicken-and-egg" typf of binary that is committed in the repo.
|
||||
It is the result of compiling `z80c.fs`, but this needs stage2.
|
||||
**Stage 0**: At this stage, all we have are our bootstrap binaries, `boot.bin`
|
||||
and `z80c.bin`. We concatenate them into `forth0.bin` ans then wrap the
|
||||
emulator around it which is named `stage1` (because it builds the stage 1) to
|
||||
have a barebone forth interpreter.
|
||||
|
||||
**Stage 1**: The `stage1` binary allows us to augment `forth0.bin` with
|
||||
the compiled dictionary of a full Forth interpreter. We feed it with
|
||||
@ -106,17 +44,25 @@ and `stage2` executables. `forth` is the interpreter you'll use.
|
||||
|
||||
**Stage 2**: `stage2` is used to resolve the chicken-and-egg problem and use
|
||||
the power of a full Forth intepreter, including an assembler, to assemble
|
||||
`z80c.bin`. This is a manual step executed through `make fbootstrap`.
|
||||
`z80c.bin`. This is a manual step executed through `make updatebootstrap`.
|
||||
|
||||
Normally, running this step should yield the exact same `z80c.bin` as before,
|
||||
unless of course you've changed the source.
|
||||
Normally, running this step should yield the exact same `boot.bin` and
|
||||
`z80c.bin` as before, unless of course you've changed the source.
|
||||
|
||||
## runbin
|
||||
|
||||
This is a very simple tool that reads binary z80 code from stdin, loads it in
|
||||
memory starting at address 0 and then run the code until it halts. The exit
|
||||
code of the program is the value of `A` when the program halts.
|
||||
|
||||
This is used for unit tests.
|
||||
|
||||
## Problems?
|
||||
|
||||
If the libz80-wrapped zasm executable works badly (hangs, spew garbage, etc.),
|
||||
it's probably because you've broken your bootstrap binaries. They're easy to
|
||||
mistakenly break. To verify if you've done that, look at your git status. If
|
||||
`kernel.bin` or `zasm.bin` are modified, try resetting them and then run
|
||||
`boot.bin` or `z80c.bin` are modified, try resetting them and then run
|
||||
`make clean all`. Things should go better afterwards.
|
||||
|
||||
If that doesn't work, there's also the nuclear option of `git reset --hard`
|
||||
|
@ -77,11 +77,6 @@ int main(int argc, char *argv[])
|
||||
m->mem[i] = KERNEL[i];
|
||||
}
|
||||
|
||||
// Our binaries don't have their LATEST offset set yet. We do this
|
||||
// on the fly, which is the simplest way to proceed ( bash script to update
|
||||
// LATEST after compilation is too simplicated )
|
||||
m->mem[0x08] = sizeof(KERNEL) & 0xff;
|
||||
m->mem[0x09] = sizeof(KERNEL) >> 8;
|
||||
// Run!
|
||||
running = 1;
|
||||
|
||||
|
@ -80,12 +80,6 @@ int main(int argc, char *argv[])
|
||||
m->mem[i] = KERNEL[i];
|
||||
}
|
||||
|
||||
// Our binaries don't have their LATEST offset set yet. We do this
|
||||
// on the fly, which is the simplest way to proceed ( bash script to update
|
||||
// LATEST after compilation is too simplicated )
|
||||
m->mem[0x08] = sizeof(KERNEL) & 0xff;
|
||||
m->mem[0x09] = sizeof(KERNEL) >> 8;
|
||||
|
||||
// Run!
|
||||
running = 1;
|
||||
|
||||
|
@ -7,6 +7,6 @@ git clean -fxd
|
||||
make -C emul
|
||||
make -C tests
|
||||
|
||||
# let's try again with an updated zasm
|
||||
# let's try again with an updated boot bin
|
||||
make -C emul updatebootstrap all
|
||||
make -C tests
|
||||
|
@ -2,9 +2,5 @@ EMULDIR = ../emul
|
||||
|
||||
.PHONY: run
|
||||
run:
|
||||
$(MAKE) -C $(EMULDIR) zasm/zasm zasm/avra runbin/runbin shell/shell forth/forth
|
||||
cd unit && ./runtests.sh
|
||||
cd zasm && ./runtests.sh
|
||||
cd avra && ./runtests.sh
|
||||
cd shell && ./runtests.sh
|
||||
$(MAKE) -C $(EMULDIR) forth/forth
|
||||
cd forth && ./runtests.sh
|
||||
|
@ -1,49 +1,4 @@
|
||||
# Testing Collapse OS
|
||||
|
||||
This folder contains Collapse OS' automated testing suite. To run, it needs
|
||||
`tools/emul` to be built. You can run all tests with `make`.
|
||||
|
||||
## zasm
|
||||
|
||||
This folder tests zasm's assembling capabilities by assembling test source files
|
||||
and compare the results with expected binaries. These binaries used to be tested
|
||||
with a golden standard assembler, scas, but at some point compatibility with
|
||||
scas was broken, so we test against previously generated binaries, making those
|
||||
tests essentially regression tests.
|
||||
|
||||
Those reference binaries sometimes change, especially when we update code in
|
||||
core libraries because some tests include them. In this case, we have to update
|
||||
binaries to the new expected value by being extra careful not to introduce a
|
||||
regression in test references.
|
||||
|
||||
## unit
|
||||
|
||||
Those tests target specific routines to test and test them using
|
||||
`tools/emul/runbin` which:
|
||||
|
||||
1. Loads the specified binary
|
||||
2. Runs it until it halts
|
||||
3. Verifies that `A` is zero. If it's not, we're in error and we display the
|
||||
value of `A`.
|
||||
|
||||
Test source code has no harnessing and is written in a very "hands on" approach.
|
||||
At the moment, debugging a test failure is a bit tricky because the error code
|
||||
often doesn't tell us much.
|
||||
|
||||
The convention is to keep a `testNum` counter variable around and call
|
||||
`nexttest` after each success so that we can easily have an idea of where we
|
||||
fail.
|
||||
|
||||
Then, if you need to debug the cause of a failure, well, you're on your own.
|
||||
However, there are tricks.
|
||||
|
||||
1. Run `unit/runtests.sh <name of file to test>` to target a specific test unit.
|
||||
2. Insert a `halt` to see the value of `A` at any given moment: it will be your
|
||||
reported error code (if 0, runbin will report a success).
|
||||
|
||||
## shell
|
||||
|
||||
Those tests are in the form of shell "replay" files. Every ".replay" file in
|
||||
this folder contains the contents to type in the shell. That contents is piped
|
||||
through the shell and the output is then compared with the corresponding
|
||||
".expected" file. If they match exactly, the test passes.
|
||||
`/emul` to be built. You can run all tests with `make`.
|
||||
|
1
tools/.gitignore
vendored
1
tools/.gitignore
vendored
@ -4,3 +4,4 @@
|
||||
/fontcompile
|
||||
/ttysafe
|
||||
/pingpong
|
||||
/slatest
|
||||
|
@ -4,8 +4,9 @@ UPLOAD_TGT = upload
|
||||
FONTCOMPILE_TGT = fontcompile
|
||||
TTYSAFE_TGT = ttysafe
|
||||
PINGPONG_TGT = pingpong
|
||||
SLATEST_TGT = slatest
|
||||
TARGETS = $(MEMDUMP_TGT) $(BLKDUMP_TGT) $(UPLOAD_TGT) $(FONTCOMPILE_TGT) \
|
||||
$(TTYSAFE_TGT) $(PINGPONG_TGT)
|
||||
$(TTYSAFE_TGT) $(PINGPONG_TGT) $(SLATEST_TGT)
|
||||
OBJS = common.o
|
||||
|
||||
all: $(TARGETS)
|
||||
@ -20,6 +21,7 @@ $(UPLOAD_TGT): $(UPLOAD_TGT).c
|
||||
$(FONTCOMPILE_TGT): $(FONTCOMPILE_TGT).c
|
||||
$(TTYSAFE_TGT): $(TTYSAFE_TGT).c
|
||||
$(PINGPONG_TGT): $(PINGPONG_TGT).c
|
||||
$(SLATEST_TGT): $(SLATEST_TGT).c
|
||||
$(TARGETS): $(OBJS)
|
||||
$(CC) $(CFLAGS) $@.c $(OBJS) -o $@
|
||||
|
||||
|
29
tools/slatest.c
Normal file
29
tools/slatest.c
Normal file
@ -0,0 +1,29 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* Update the "LATEST" offset of target Forth binary according to filesize. */
|
||||
|
||||
#define OFFSET 0x08
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "Usage: ./slatest fname\n");
|
||||
return 1;
|
||||
}
|
||||
FILE *fp = fopen(argv[1], "r+");
|
||||
if (!fp) {
|
||||
fprintf(stderr, "Can't open %s.\n", argv[1]);
|
||||
return 1;
|
||||
}
|
||||
fseek(fp, 0, SEEK_END);
|
||||
unsigned int bytecount = ftell(fp);
|
||||
fseek(fp, OFFSET, SEEK_SET);
|
||||
char buf[2];
|
||||
buf[0] = bytecount & 0xff;
|
||||
buf[1] = bytecount >> 8;
|
||||
fwrite(buf, 2, 1, fp);
|
||||
fclose(fp);
|
||||
}
|
Loading…
Reference in New Issue
Block a user