From 9ec71ecfeef9127373442a21128966725ef62694 Mon Sep 17 00:00:00 2001 From: Virgil Dupras Date: Mon, 9 Dec 2019 22:01:22 -0500 Subject: [PATCH] tools/uploadb: rewrite in C --- tools/.gitignore | 2 ++ tools/Makefile | 21 ++++++++++----- tools/common.c | 19 +++++++++++++ tools/common.h | 2 ++ tools/emul/.gitignore | 1 - tools/memdump.c | 18 ++----------- tools/upload.c | 65 ++++++++++++++++++++++++++++++++++++++++++++ tools/uploadb.pl | 75 --------------------------------------------------- 8 files changed, 105 insertions(+), 98 deletions(-) create mode 100644 tools/common.c create mode 100644 tools/common.h create mode 100644 tools/upload.c delete mode 100755 tools/uploadb.pl diff --git a/tools/.gitignore b/tools/.gitignore index 14d909d..0c44728 100644 --- a/tools/.gitignore +++ b/tools/.gitignore @@ -1 +1,3 @@ +*.o /memdumpb +/uploadb diff --git a/tools/Makefile b/tools/Makefile index 577e358..580ea8b 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -1,13 +1,22 @@ -CFLAGS ?= -Wall - MEMDUMP_TGT = memdumpb MEMDUMP_SRC = memdump.c +UPLOAD_TGT = uploadb +UPLOAD_SRC = upload.c +TARGETS = $(MEMDUMP_TGT) $(UPLOAD_TGT) +OBJS = common.o + +all: $(TARGETS) + +.SUFFIXES: .c .o +.c.o: + $(CC) $(CFLAGS) -c $< -o $@ -all: ${MEMDUMP_TGT} +$(MEMDUMP_TGT): $(MEMDUMP_SRC) $(OBJS) + $(CC) $(CFLAGS) $(MEMDUMP_SRC) $(OBJS) -o $@ -${MEMDUMP_TGT}: ${MEMDUMP_SRC} - ${CC} ${CFLAGS} ${MEMDUMP_SRC} -o ${MEMDUMP_TGT} +$(UPLOAD_TGT): $(UPLOAD_SRC) $(OBJS) + $(CC) $(CFLAGS) $(UPLOAD_SRC) $(OBJS) -o $@ .PHONY: clean clean: - rm -f ${MEMDUMP_TGT} + rm -f $(TARGETS) $(OBJS) diff --git a/tools/common.c b/tools/common.c new file mode 100644 index 0000000..b81183a --- /dev/null +++ b/tools/common.c @@ -0,0 +1,19 @@ +#include +#include + +void sendcmd(int fd, char *cmd) +{ + char junk[2]; + while (*cmd) { + write(fd, cmd, 1); + read(fd, &junk, 1); + cmd++; + // The other side is sometimes much slower than us and if we don't let + // it breathe, it can choke. + usleep(1000); + } + write(fd, "\n", 1); + read(fd, &junk, 2); // sends back \r\n + usleep(1000); +} + diff --git a/tools/common.h b/tools/common.h new file mode 100644 index 0000000..4ab7af8 --- /dev/null +++ b/tools/common.h @@ -0,0 +1,2 @@ +void sendcmd(int fd, char *cmd); + diff --git a/tools/emul/.gitignore b/tools/emul/.gitignore index 3d1bbc7..2b9ca3c 100644 --- a/tools/emul/.gitignore +++ b/tools/emul/.gitignore @@ -8,4 +8,3 @@ /cfsin/ed /cfsin/basic /cfsin/user.h -*.o diff --git a/tools/memdump.c b/tools/memdump.c index 756ec7f..f782a8a 100644 --- a/tools/memdump.c +++ b/tools/memdump.c @@ -3,26 +3,12 @@ #include #include +#include "common.h" + /* Read specified number of bytes at specified memory address through a BASIC * remote shell and dump it to stdout. */ -void sendcmd(int fd, char *cmd) -{ - char junk[2]; - while (*cmd) { - write(fd, cmd, 1); - read(fd, &junk, 1); - cmd++; - // The other side is sometimes much slower than us and if we don't let - // it breathe, it can choke. - usleep(1000); - } - write(fd, "\n", 1); - read(fd, &junk, 2); // sends back \r\n - usleep(1000); -} - int main(int argc, char **argv) { if (argc != 4) { diff --git a/tools/upload.c b/tools/upload.c new file mode 100644 index 0000000..b67b684 --- /dev/null +++ b/tools/upload.c @@ -0,0 +1,65 @@ +#include +#include +#include +#include + +#include "common.h" + +/* Push specified file to specified device **running the BASIC shell** and verify + * that the sent contents is correct. + */ + +int main(int argc, char **argv) +{ + if (argc != 4) { + fprintf(stderr, "Usage: ./upload device memptr fname\n"); + return 1; + } + unsigned int memptr = strtol(argv[2], NULL, 16); + FILE *fp = fopen(argv[3], "r"); + if (!fp) { + fprintf(stderr, "Can't open %s.\n", argv[3]); + return 1; + } + fseek(fp, 0, SEEK_END); + unsigned int bytecount = ftell(fp); + fprintf(stderr, "memptr: 0x%04x bytecount: 0x%04x.\n", memptr, bytecount); + if (memptr+bytecount > 0xffff) { + fprintf(stderr, "memptr+bytecount out of range.\n"); + fclose(fp); + return 1; + } + rewind(fp); + int fd = open(argv[1], O_RDWR|O_NOCTTY); + char s[0x10]; + sprintf(s, "m=0x%04x", memptr); + sendcmd(fd, s); + read(fd, s, 2); // read prompt + + while (fread(s, 1, 1, fp)) { + putchar('.'); + fflush(stdout); + unsigned char c = s[0]; + sendcmd(fd, "getc"); + write(fd, &c, 1); + read(fd, s, 2); // read prompt + sendcmd(fd, "puth a"); + read(fd, s, 2); // read hex pair + s[2] = 0; // null terminate + unsigned char c2 = strtol(s, NULL, 16); + read(fd, s, 2); // read prompt + if (c != c2) { + // mismatch! + unsigned int pos = ftell(fp); + fprintf(stderr, "Mismatch at byte %d! %d != %d.\n", pos, c, c2); + return 1; + } + sendcmd(fd, "poke m a"); + read(fd, s, 2); // read prompt + sendcmd(fd, "m=m+1"); + read(fd, s, 2); // read prompt + } + printf("Done!\n"); + return 0; +} + diff --git a/tools/uploadb.pl b/tools/uploadb.pl deleted file mode 100755 index 6ae03ad..0000000 --- a/tools/uploadb.pl +++ /dev/null @@ -1,75 +0,0 @@ -#!/usr/bin/perl -# Push specified file to specified device **running the BASIC shell** and verify -# that the sent contents is correct. -use strict; -use Fcntl; - -if (@ARGV != 3) { - print "Usage: ./uploadb.pl device memptr filename\n"; - exit 1; -} - -my ($device, $memptr, $fname) = @ARGV; - -if (hex($memptr) >= 0x10000) { die "memptr is out of range"; } - -if (! -e $fname) { die "${fname} does not exist"; } -my $fsize = -s $fname; -my $maxsize = 0x10000 - hex($memptr); -if ($fsize > $maxsize) { die "File too big. ${maxsize} bytes max"; } - -my $fh; -unless (open($fh, '<', $fname)) { die "Can't open $fname"; } - -my $devh; -unless (sysopen($devh, $device, O_RDWR|O_NOCTTY)) { die "Can't open $device"; } - -sub sendcmd { - # The serial link echoes back all typed characters and expects us to read - # them. We have to send each char one at a time. - my $junk; - foreach my $char (split //, shift) { - syswrite $devh, $char; - sysread $devh, $junk, 1; - } - syswrite $devh, "\n"; - sysread $devh, $junk, 2; # send back \r\n -} - -sendcmd("m=0x${memptr}"); - -my $rd; -sysread $devh, $rd, 2; # read prompt - -# disable buffering -$| = 1; - -while (sysread $fh, my $char, 1) { - print "."; - for (my $i=0; $i<5; $i++) { # try 5 times - sendcmd("getc"); - syswrite $devh, $char; - sysread $devh, $rd, 2; # read prompt - sendcmd("puth a"); - sysread $devh, $rd, 2; - my $ri = hex($rd); - sysread $devh, $rd, 2; # read prompt - if ($ri == ord($char)) { - last; - } else { - if ($i < 4) { - print "Mismatch at byte ${i}! ${ri} != ${ord($char)}. Retrying.\n"; - } else { - die "Maximum retries reached, abort.\n"; - } - } - } - sendcmd("poke m a"); - sysread $devh, $rd, 2; # read prompt - sendcmd("m=m+1"); - sysread $devh, $rd, 2; # read prompt -} - -print "Done!\n"; -close $fh; -close $devh;