diff options
author | H. Peter Anvin <hpa@zytor.com> | 2010-02-05 18:03:14 -0800 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2010-02-05 18:03:14 -0800 |
commit | 3dededd20d70d571268417dc41edc95f0fe6602e (patch) | |
tree | a3c64b598884588323d6f0c08c9034a30f3f9b95 | |
parent | 88c00aca310b7bade07833d3021cae9da266eae7 (diff) | |
download | syslinux.git-3dededd20d70d571268417dc41edc95f0fe6602e.tar.gz syslinux.git-3dededd20d70d571268417dc41edc95f0fe6602e.tar.xz syslinux.git-3dededd20d70d571268417dc41edc95f0fe6602e.zip |
memdump: allow outputting S-records
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>
-rw-r--r-- | memdump/Makefile | 2 | ||||
-rw-r--r-- | memdump/file.h | 25 | ||||
-rw-r--r-- | memdump/main.c | 30 | ||||
-rw-r--r-- | memdump/serial.c | 5 | ||||
-rw-r--r-- | memdump/srecsend.c | 80 | ||||
-rw-r--r-- | memdump/srecsend.h | 10 | ||||
-rw-r--r-- | memdump/stdbool.h | 32 | ||||
-rw-r--r-- | memdump/ymsend.h | 18 |
8 files changed, 176 insertions, 26 deletions
diff --git a/memdump/Makefile b/memdump/Makefile index 05f26383..e56c7bd4 100644 --- a/memdump/Makefile +++ b/memdump/Makefile @@ -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 index 00000000..8da6973d --- /dev/null +++ b/memdump/file.h @@ -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 */ diff --git a/memdump/main.c b/memdump/main.c index 02f2a4fc..068f657e 100644 --- a/memdump/main.c +++ b/memdump/main.c @@ -13,8 +13,10 @@ #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; } diff --git a/memdump/serial.c b/memdump/serial.c index c8330f71..1c613d17 100644 --- a/memdump/serial.c +++ b/memdump/serial.c @@ -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 index 00000000..668d16cb --- /dev/null +++ b/memdump/srecsend.c @@ -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 index 00000000..f2b08224 --- /dev/null +++ b/memdump/srecsend.h @@ -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 index 00000000..81cb05f5 --- /dev/null +++ b/memdump/stdbool.h @@ -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 */ diff --git a/memdump/ymsend.h b/memdump/ymsend.h index daed627d..b0d74384 100644 --- a/memdump/ymsend.h +++ b/memdump/ymsend.h @@ -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 */ |