dragon-mooh: Build and use DECB patcher for kernel image
authorTormod Volden <debian.tormod@gmail.com>
Thu, 13 Sep 2018 21:13:44 +0000 (23:13 +0200)
committerAlan Cox <alan@linux.intel.com>
Fri, 14 Sep 2018 11:01:04 +0000 (12:01 +0100)
The decb-mooh tool modifies a plain DECB binary so that it
can load onto the MOOH with e.g. the SDBOOT bootloader.

Signed-off-by: Tormod Volden <debian.tormod@gmail.com>
Kernel/cpu-6809/rules.mk
Kernel/platform-dragon-mooh/Makefile
Kernel/tools/decb-mooh.c [new file with mode: 0644]

index e0ebc88..44015df 100644 (file)
@@ -23,4 +23,5 @@ export BITS=16
 
 tools/decbdragon: tools/decbdragon.c
 tools/decb-image: tools/decb-image.c
+tools/decb-mooh: tools/decb-mooh.c
 
index 8627480..a52a354 100644 (file)
@@ -57,7 +57,7 @@ $(AOBJS): %$(BINEXT): %.s
 clean:
        rm -f $(OBJS) $(JUNK)
 
-image:
+image: ../tools/decb-mooh
        $(CROSS_LD) -o ../fuzix.bin -Map=../fuzix.map --script=fuzix.link --oformat=decb \
        crt0.o commonmem.o usermem_sam.o \
        dragon.o mem-mooh.o ../bank8k.o \
@@ -76,3 +76,5 @@ image:
        discard.o
        ../tools/pad256 ../fuzix.bin
        ../tools/lw-checkmap ../fuzix.map
+       ../tools/decb-mooh < ../fuzix.bin > ../fuzix-mooh.bin
+       mv ../fuzix-mooh.bin ../fuzix.bin
diff --git a/Kernel/tools/decb-mooh.c b/Kernel/tools/decb-mooh.c
new file mode 100644 (file)
index 0000000..79390bf
--- /dev/null
@@ -0,0 +1,133 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdbool.h>
+
+/*
+ *   Shift loading address of low-address DECB segments
+ *
+ *   Segments below 0x2000 are shifted up 0x2000 bytes so
+ *   that they can be initially loaded into an MMU bank
+ *   which will be consecutively mapped at 0x0000.
+ *
+ *   Also map in banks that the bootloader won't.
+ */
+
+static enum {
+  NEW_BLOCK,
+  PREAMBLE_1,
+  PREAMBLE_2,
+  PREAMBLE_3,
+  PREAMBLE_4,
+  POSTAMBLE_1,
+  POSTAMBLE_2,
+  POSTAMBLE_3,
+  POSTAMBLE_4,
+  DONE,
+  BYTESTREAM
+} state = NEW_BLOCK;
+
+int main(int argc, char *argv[])
+{
+  unsigned int c;
+  unsigned int base, size;
+  unsigned int execmsb;
+  bool shifted = false;
+
+  /* map banks 5,6,7 at 0x2000-0x7fff */
+  printf("%c%c%c%c%c%c", 0, 0, 0x01, 0xff, 0xa1, 0x05);
+  printf("%c%c%c%c%c%c", 0, 0, 0x01, 0xff, 0xa2, 0x06);
+  printf("%c%c%c%c%c%c", 0, 0, 0x01, 0xff, 0xa3, 0x07);
+
+  while(state != DONE && (c = getchar()) != EOF) {
+    switch(state) {
+      case NEW_BLOCK:
+        if (c == 0xFF) {
+          state = POSTAMBLE_1;
+          break;
+        }
+        if (c == 0x00) {
+          state = PREAMBLE_1;
+          break;
+        }
+        fprintf(stderr, "Corrupt DECB (%d)\n", c);
+        exit(1);
+        break;
+
+      case POSTAMBLE_1:
+        if (c != 0x00) {
+          fprintf(stderr, "DECB postamble byte 0 not 0x00\n");
+          exit(1);
+        }
+        state = POSTAMBLE_2;
+        break;
+      case POSTAMBLE_2:
+        if (c != 0x00) {
+          fprintf(stderr, "DECB postamble byte 2 not 0x00\n");
+          exit(1);
+        }
+        state = POSTAMBLE_3;
+        break;
+      case POSTAMBLE_3:
+        execmsb = c;
+        state = POSTAMBLE_4;
+        break;
+      case POSTAMBLE_4:
+        state = DONE;
+        /* write out postamble */
+        printf("%c%c%c%c%c", 0xff, 0, 0, execmsb, c);
+        break;
+
+      case PREAMBLE_1:
+        size = c << 8;
+        state = PREAMBLE_2;
+        break;
+      case PREAMBLE_2:
+        size += c;
+        state = PREAMBLE_3;
+        break;
+      case PREAMBLE_3:
+        if (c < 0x20) {
+            c += 0x20; /* shift it up */
+            if (!shifted) {
+               /* map bank 4 temporarily at 0x2000 */
+                printf("%c%c%c%c%c%c", 0, 0, 0x01, 0xff, 0xa1, 0x04);
+                shifted = true;
+            }
+        } else if (shifted) {
+           /* map back bank 5 at 0x2000 */
+            printf("%c%c%c%c%c%c", 0, 0, 0x01, 0xff, 0xa1, 0x05);
+            shifted = false;
+        }
+        base = c << 8;
+        state = PREAMBLE_4;
+        break;
+      case PREAMBLE_4:
+        base += c;
+        state = BYTESTREAM;
+        if (base + size > 65535) {
+          fprintf(stderr, "Oversized image\n");
+          exit(1);
+        }
+        /* write out preamble */
+        printf("%c%c%c%c%c", 0, size >> 8, size & 0xFF, base >> 8, c);
+        fprintf(stderr, "preamble %04x (%04x)\n", base, size);
+        break;
+      case BYTESTREAM:
+        printf("%c", c);
+        size--;
+        if (size == 0)
+          state = NEW_BLOCK;
+        break;
+      default:
+        fprintf(stderr, "State machine horked.\n");
+        exit(1);
+    }
+  }
+  if (state != DONE) {
+    fprintf(stderr, "Unexpected EOF in state %d\n", state);
+    exit(1);
+  }
+  exit(0);
+}