@@ -1 +1,3 @@ | |||
*.o | |||
/memdumpb | |||
/uploadb |
@@ -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) |
@@ -0,0 +1,19 @@ | |||
#include <stdlib.h> | |||
#include <unistd.h> | |||
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); | |||
} | |||
@@ -0,0 +1,2 @@ | |||
void sendcmd(int fd, char *cmd); | |||
@@ -8,4 +8,3 @@ | |||
/cfsin/ed | |||
/cfsin/basic | |||
/cfsin/user.h | |||
*.o |
@@ -3,26 +3,12 @@ | |||
#include <fcntl.h> | |||
#include <unistd.h> | |||
#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) { | |||
@@ -0,0 +1,65 @@ | |||
#include <stdlib.h> | |||
#include <stdio.h> | |||
#include <fcntl.h> | |||
#include <unistd.h> | |||
#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; | |||
} | |||
@@ -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; |