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.

121 lines
2.8KB

  1. #include <stdint.h>
  2. #include <stdio.h>
  3. #include <unistd.h>
  4. #include "emul.h"
  5. #ifdef STAGE2
  6. #include "stage1-bin.h"
  7. #include "blkfs-bin.h"
  8. #else
  9. #include "stage0-bin.h"
  10. #endif
  11. /* Staging binaries
  12. The role of a stage executable is to compile definitions in a dictionary and
  13. then spit the difference between the starting binary and the new binary.
  14. That binary can then be grafted to an exiting Forth binary to augment its
  15. dictionary.
  16. We could, if we wanted, run only with the bootstrap binary and compile core
  17. defs at runtime, but that would mean that those defs live in RAM. In may system,
  18. RAM is much more constrained than ROM, so it's worth it to give ourselves the
  19. trouble of compiling defs to binary.
  20. */
  21. // When DEBUG is set, stage1 is a core-less forth that works interactively.
  22. // Useful for... debugging!
  23. // By the way: there's a double-echo in stagedbg. It's normal. Don't panic.
  24. //#define DEBUG
  25. #define RAMSTART 0
  26. #define STDIO_PORT 0x00
  27. // To know which part of RAM to dump, we listen to port 2, which at the end of
  28. // its compilation process, spits its HERE addr to port 2 (MSB first)
  29. #define HERE_PORT 0x02
  30. // Port for block reads. Write 2 bytes, MSB first, on that port and then
  31. // read 1024 bytes from the DATA port.
  32. #define BLK_PORT 0x03
  33. #define BLKDATA_PORT 0x04
  34. static int running;
  35. // We support double-pokes, that is, a first poke to tell where to start the
  36. // dump and a second one to tell where to stop. If there is only one poke, it's
  37. // then ending HERE and we start at sizeof(KERNEL).
  38. static uint16_t start_here = 0;
  39. static uint16_t end_here = 0;
  40. static uint16_t blkid = 0;
  41. static unsigned int blkpos = 0;
  42. static uint8_t iord_stdio()
  43. {
  44. int c = getc(stdin);
  45. if (c == EOF) {
  46. running = 0;
  47. }
  48. return (uint8_t)c;
  49. }
  50. static void iowr_stdio(uint8_t val)
  51. {
  52. // we don't output stdout in stage0
  53. #ifdef DEBUG
  54. // ... unless we're in DEBUG mode!
  55. putchar(val);
  56. #endif
  57. }
  58. static void iowr_here(uint8_t val)
  59. {
  60. start_here <<=8;
  61. start_here |= (end_here >> 8);
  62. end_here <<= 8;
  63. end_here |= val;
  64. }
  65. #ifdef STAGE2
  66. static void iowr_blk(uint8_t val)
  67. {
  68. blkid <<= 8;
  69. blkid |= val;
  70. blkpos = blkid * 1024;
  71. }
  72. static uint8_t iord_blkdata()
  73. {
  74. return BLKFS[blkpos++];
  75. }
  76. #endif
  77. int main(int argc, char *argv[])
  78. {
  79. Machine *m = emul_init();
  80. m->ramstart = RAMSTART;
  81. m->iord[STDIO_PORT] = iord_stdio;
  82. m->iowr[STDIO_PORT] = iowr_stdio;
  83. m->iowr[HERE_PORT] = iowr_here;
  84. #ifdef STAGE2
  85. m->iowr[BLK_PORT] = iowr_blk;
  86. m->iord[BLKDATA_PORT] = iord_blkdata;
  87. #endif
  88. // initialize memory
  89. for (int i=0; i<sizeof(KERNEL); i++) {
  90. m->mem[i] = KERNEL[i];
  91. }
  92. // Run!
  93. running = 1;
  94. while (running && emul_step());
  95. #ifndef DEBUG
  96. // We're done, now let's spit dict data
  97. for (int i=start_here; i<end_here; i++) {
  98. putchar(m->mem[i]);
  99. }
  100. #endif
  101. return 0;
  102. }