Mirror of CollapseOS
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

glue-code.md 5.4KB

5 jaren geleden
5 jaren geleden
5 jaren geleden
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. # Writing the glue code
  2. Collapse OS's kernel code is loosely knit. It supplies parts that you're
  3. expected to glue together in a "glue code" asm file. Here is what a minimal
  4. glue code for a shell on a Classic [RC2014][rc2014] with an ACIA link would
  5. look like:
  6. ; The RAM module is selected on A15, so it has the range 0x8000-0xffff
  7. .equ RAMSTART 0x8000
  8. .equ RAMEND 0xffff
  9. .equ ACIA_CTL 0x80 ; Control and status. RS off.
  10. .equ ACIA_IO 0x81 ; Transmit. RS on.
  11. jp init
  12. ; interrupt hook
  13. .fill 0x38-$
  14. jp aciaInt
  15. .inc "err.h"
  16. .inc "ascii.h"
  17. .inc "core.asm"
  18. .inc "str.asm"
  19. .inc "parse.asm"
  20. .equ ACIA_RAMSTART RAMSTART
  21. .inc "acia.asm"
  22. .equ STDIO_RAMSTART ACIA_RAMEND
  23. .equ STDIO_GETC aciaGetC
  24. .equ STDIO_PUTC aciaPutC
  25. .inc "stdio.asm"
  26. ; *** BASIC ***
  27. ; RAM space used in different routines for short term processing.
  28. .equ SCRATCHPAD_SIZE 0x20
  29. .equ SCRATCHPAD STDIO_RAMEND
  30. .inc "lib/util.asm"
  31. .inc "lib/ari.asm"
  32. .inc "lib/parse.asm"
  33. .inc "lib/fmt.asm"
  34. .equ EXPR_PARSE parseLiteralOrVar
  35. .inc "lib/expr.asm"
  36. .inc "basic/util.asm"
  37. .inc "basic/parse.asm"
  38. .inc "basic/tok.asm"
  39. .equ VAR_RAMSTART SCRATCHPAD+SCRATCHPAD_SIZE
  40. .inc "basic/var.asm"
  41. .equ BUF_RAMSTART VAR_RAMEND
  42. .inc "basic/buf.asm"
  43. .equ BAS_RAMSTART BUF_RAMEND
  44. .inc "basic/main.asm"
  45. init:
  46. di
  47. ; setup stack
  48. ld sp, RAMEND
  49. im 1
  50. call aciaInit
  51. call basInit
  52. ei
  53. jp basStart
  54. Once this is written, you can build it with `zasm`, which takes code from stdin
  55. and spits binary to stdout. Because out code has includes, however, you need
  56. to supply zasm with a block device containing a CFS containing the files to
  57. include. This sounds, compicated, but it's managed by the `tools/zasm.sh` shell
  58. script. The invocation would look like (it builds a CFS with the contents of
  59. both `kernel/` and `apps/` folders):
  60. tools/zasm.sh kernel/ apps/ < glue.asm > collapseos.bin
  61. ## Building zasm
  62. Collapse OS has its own assembler written in z80 assembly. We call it
  63. [zasm][zasm]. Even on a "modern" machine, it is that assembler that is used,
  64. but because it is written in z80 assembler, it needs to be emulated (with
  65. [libz80][libz80]).
  66. So, the first step is to build zasm. Open `tools/emul/README.md` and follow
  67. instructions there.
  68. ## Platform constants
  69. The upper part of the code contains platform-related constants, information
  70. related to the platform you're targeting. You might want to put it in an
  71. include file if you're writing multiple glue code that targets the same machine.
  72. In all cases, `RAMSTART` are necessary. `RAMSTART` is the offset at which
  73. writable memory begins. This is where the different parts store their
  74. variables.
  75. `RAMEND` is the offset where writable memory stop. This is generally
  76. where we put the stack, but as you can see, setting up the stack is the
  77. responsibility of the glue code, so you can set it up however you wish.
  78. `ACIA_*` are specific to the `acia` part. Details about them are in `acia.asm`.
  79. If you want to manage ACIA, you need your platform to define these ports.
  80. ## Header code
  81. Then comes the header code (code at `0x0000`), a task that also is in the glue
  82. code's turf. `jr init` means that we run our `init` routine on boot.
  83. `jp aciaInt` at `0x38` is needed by the `acia` part. Collapse OS doesn't dictate
  84. a particular interrupt scheme, but some parts might. In the case of `acia`, we
  85. require to be set in interrupt mode 1.
  86. ## Includes
  87. This is the most important part of the glue code and it dictates what will be
  88. included in your OS. Each part is different and has a comment header explaining
  89. how it works, but there are a couple of mechanisms that are common to all.
  90. ### Defines
  91. Parts can define internal constants, but also often document a "Defines" part.
  92. These are constant that are expected to be set before you include the file.
  93. See comment in each part for details.
  94. ### RAM management
  95. Many parts require variables. They need to know where in RAM to store these
  96. variables. Because parts can be mixed and matched arbitrarily, we can't use
  97. fixed memory addresses.
  98. This is why each part that needs variable define a `<PARTNAME>_RAMSTART`
  99. constant that must be defined before we include the part.
  100. Symmetrically, each part define a `<PARTNAME>_RAMEND` to indicate where its
  101. last variable ends.
  102. This way, we can easily and efficiently chain up the RAM of every included part.
  103. ### Tables grafting
  104. A mechanism that is common to some parts is "table grafting". If a part works
  105. on a list of things that need to be defined by the glue code, it will place a
  106. label at the very end of its source file. This way, it becomes easy for the
  107. glue code to "graft" entries to the table. This approach, although simple and
  108. effective, only works for one table per part. But it's often enough.
  109. For example, to define block devices:
  110. [...]
  111. .equ BLOCKDEV_COUNT 4
  112. .inc "blockdev.asm"
  113. ; List of devices
  114. .dw fsdevGetB, fsdevPutB
  115. .dw stdoutGetB, stdoutPutB
  116. .dw stdinGetB, stdinPutB
  117. .dw mmapGetB, mmapPutB
  118. [...]
  119. ### Initialization
  120. Then, finally, comes the `init` code. This can be pretty much anything really
  121. and this much depends on the part you select. But if you want a shell, you will
  122. usually end it with `basStart`, which never returns.
  123. [rc2014]: https://rc2014.co.uk/
  124. [zasm]: ../tools/emul/README.md
  125. [libz80]: https://github.com/ggambetta/libz80