memdump: allow outputting S-records
authorH. Peter Anvin <hpa@zytor.com>
Sat, 6 Feb 2010 02:03:14 +0000 (18:03 -0800)
committerH. Peter Anvin <hpa@zytor.com>
Sat, 6 Feb 2010 02:03:14 +0000 (18:03 -0800)
Allow outputting S-records, for users who only have the capability of
passively monitoring a serial port as opposed to being able to capture
the contents directly.

Signed-off-by: H. Peter Anvin <hpa@zytor.com>
memdump/Makefile
memdump/file.h [new file with mode: 0644]
memdump/main.c
memdump/serial.c
memdump/srecsend.c [new file with mode: 0644]
memdump/srecsend.h [new file with mode: 0644]
memdump/stdbool.h [new file with mode: 0644]
memdump/ymsend.h

index 05f2638..e56c7bd 100644 (file)
@@ -21,7 +21,7 @@ OPTFLAGS =
 INCLUDES = -include code16.h -I.
 LDFLAGS         = -T com16.ld
 
-SRCS     = main.c serial.c ymsend.c
+SRCS     = main.c serial.c ymsend.c srecsend.c
 OBJS    = crt0.o $(patsubst %.c,%.o,$(notdir $(SRCS)))
 LIBOBJS         = conio.o memcpy.o memset.o skipatou.o strtoul.o \
           argv.o printf.o __divdi3.o __udivmoddi4.o
diff --git a/memdump/file.h b/memdump/file.h
new file mode 100644 (file)
index 0000000..8da6973
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef FILE_H
+#define FILE_H
+
+#include "mystuff.h"
+
+struct serial_if {
+    int port;
+    void *pvt;
+    void (*read) (struct serial_if *, void *, size_t);
+    void (*write) (struct serial_if *, const void *, size_t);
+};
+
+struct file_info {
+    const char *name;
+    size_t base;
+    size_t size;
+    void *pvt;
+};
+
+
+int serial_init(struct serial_if *sif);
+void serial_read(struct serial_if *sif, void *data, size_t n);
+void serial_write(struct serial_if *sif, const void *data, size_t n);
+
+#endif /* FILE_H */
index 02f2a4f..068f657 100644 (file)
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
+#include <stdbool.h>
 #include "mystuff.h"
 #include "ymsend.h"
+#include "srecsend.h"
 #include "io.h"
 
 const char *program = "memdump";
@@ -89,10 +91,17 @@ int main(int argc, char *argv[])
        .write = serial_write,
     };
     struct file_info finfo;
-    const char serial_banner[] = "Now begin Ymodem download...\r\n";
+    const char ymodem_banner[] = "Now begin Ymodem download...\r\n";
+    bool srec = false;
+
+    if (argv[1][0] == '-') {
+       srec = argv[1][1] == 's';
+       argc--;
+       argv++;
+    }
 
     if (argc < 4)
-       die("usage: memdump port prefix start,len...");
+       die("usage: memdump [-s] port prefix start,len...");
 
     finfo.pvt = (void *)0x400;
     get_bytes(bios_ports, 8, &finfo, 0);       /* Get BIOS serial ports */
@@ -110,8 +119,10 @@ int main(int argc, char *argv[])
 
     prefix = argv[2];
 
-    puts("Printing prefix...\n");
-    sif.write(&sif, serial_banner, sizeof serial_banner - 1);
+    if (!srec) {
+       puts("Printing prefix...\n");
+       sif.write(&sif, ymodem_banner, sizeof ymodem_banner - 1);
+    }
 
     for (i = 3; i < argc; i++) {
        uint32_t start, len;
@@ -131,11 +142,16 @@ int main(int argc, char *argv[])
        puts(filename);
        puts("...\n");
 
-       send_ymodem(&sif, &finfo, get_bytes);
+       if (srec)
+           send_srec(&sif, &finfo, get_bytes);
+       else
+           send_ymodem(&sif, &finfo, get_bytes);
     }
 
-    puts("Sending closing signature...\n");
-    end_ymodem(&sif);
+    if (!srec) {
+       puts("Sending closing signature...\n");
+       end_ymodem(&sif);
+    }
 
     return 0;
 }
index c8330f7..1c613d1 100644 (file)
@@ -1,5 +1,8 @@
+#include <stdbool.h>
+#include <stdio.h>
+
 #include "mystuff.h"
-#include "ymsend.h"
+#include "file.h"
 #include "io.h"
 
 enum {
diff --git a/memdump/srecsend.c b/memdump/srecsend.c
new file mode 100644 (file)
index 0000000..668d16c
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * SREC send routine.
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include "srecsend.h"
+
+static void make_srec(struct serial_if *sif, char type, size_t addr,
+                     const void *data, size_t len)
+{
+    char buf[80];              /* More than the largest possible size */
+    char *p;
+    const uint8_t *dp = data;
+    size_t alen = (type == '0') ? 4 : 8;
+    uint8_t csum;
+
+    p = buf;
+    *p++ = 'S';
+    *p++ = type;
+    if (type == '0')
+       p += sprintf(p, "%04zX", addr);
+    else
+       p += sprintf(p, "%08zX", addr);
+    
+    csum = (len+alen+1) + addr + (addr >> 8) + (addr >> 16) + (addr >> 24);
+    while (len) {
+       p += sprintf(p, "%02X", *dp);
+       csum += *dp;
+       dp++;
+    }
+    csum = 0xff - csum;
+    p += sprintf(p, "%02X\r\n", csum);
+
+    sif->write(sif, buf, p-buf);
+}
+
+void send_srec(struct serial_if *sif, struct file_info *fileinfo,
+              void (*gen_data) (void *, size_t, struct file_info *, size_t))
+{
+    uint8_t blk_buf[1024];
+    const uint8_t *np;
+    size_t addr, len, bytes, chunk, offset, pos;
+    int blk;
+
+    len = fileinfo->size;
+
+    make_srec(sif, '0', 0, NULL, 0);
+
+    blk = 0;
+    pos = 0;
+    addr = fileinfo->base;
+    while (len) {
+       gen_data(blk_buf, sizeof blk_buf, fileinfo, pos);
+       pos += sizeof blk_buf;
+       bytes = sizeof blk_buf;
+       if (bytes > len)
+           bytes = len;
+       len -= bytes;
+
+       printf("Sending block %d...\r", blk);
+       
+       np = blk_buf;
+       while (bytes) {
+           chunk = bytes > 64 ? 64 : bytes;
+
+           make_srec(sif, '3', addr, np, chunk);
+
+           bytes -= chunk;
+           offset += chunk;
+           np += chunk;
+           addr += chunk;
+       }
+       blk++;
+    }
+
+    printf("\nSending EOT...\n");
+    make_srec(sif, '7', fileinfo->base, NULL, 0);
+    printf("Done.\n");
+}
diff --git a/memdump/srecsend.h b/memdump/srecsend.h
new file mode 100644 (file)
index 0000000..f2b0822
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef SRECSEND_H
+#define SRECSEND_H
+
+#include "mystuff.h"
+#include "file.h"
+
+void send_srec(struct serial_if *, struct file_info *,
+                void (*)(void *, size_t, struct file_info *, size_t));
+
+#endif /* SRECSEND_H */
diff --git a/memdump/stdbool.h b/memdump/stdbool.h
new file mode 100644 (file)
index 0000000..81cb05f
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ *
+ * stdbool.h
+ */
+
+#ifndef _STDBOOL_H
+#define _STDBOOL_H
+
+#ifndef __cplusplus
+
+#if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L)
+# if !defined(__GNUC__) ||(__GNUC__ < 3)
+typedef char _Bool;            /* For C compilers without _Bool */
+# endif
+#endif
+
+#define bool  _Bool
+#define true  1
+#define false 0
+
+#else
+
+/* C++ */
+#define bool  bool
+#define true  true
+#define false false
+
+#endif
+
+#define __bool_true_false_are_defined 1
+
+#endif /* _STDBOOL_H */
index daed627..b0d7438 100644 (file)
@@ -2,26 +2,10 @@
 #define YMSEND_H
 
 #include "mystuff.h"
-
-struct serial_if {
-    int port;
-    void *pvt;
-    void (*read) (struct serial_if *, void *, size_t);
-    void (*write) (struct serial_if *, const void *, size_t);
-};
-
-struct file_info {
-    const char *name;
-    size_t size;
-    void *pvt;
-};
+#include "file.h"
 
 void send_ymodem(struct serial_if *, struct file_info *,
                 void (*)(void *, size_t, struct file_info *, size_t));
 void end_ymodem(struct serial_if *);
 
-int serial_init(struct serial_if *sif);
-void serial_read(struct serial_if *sif, void *data, size_t n);
-void serial_write(struct serial_if *sif, const void *data, size_t n);
-
 #endif /* YMSEND_H */