So far, I hadn't managed to run those tools properly on OpenBSD. I was too confused by its stty peculiarities. I'm still confused, but at least I managed to make them work... most of the time...master
@@ -0,0 +1,28 @@ | |||||
# Tools | |||||
This folder contains tools to communicate to Collapse OS machines from a modern | |||||
environment or to manipulate a blkfs. | |||||
Communication tools all take a device path as a first argument. That device is | |||||
the serial device that connects you to your machine. It's often a USB-to-TTL | |||||
dongle. When `-` is specified, `stdin` is used as the device. | |||||
Note that for these tools to work well, you need the serial device to be | |||||
properly set up, TTY-wise. You'll probably want to do that with `stty`. The tool | |||||
itself takes care of setting the regular stuff (`cs8`, `-parenb`, etc), but you | |||||
need to set the speed. Here's an example working on OpenBSD: | |||||
$ ( stty 115200 ; ./upload - a000 os.bin ) <>/dev/cuaU0 | |||||
To be honest, I'm having a bit of troubles making these tools work as well on | |||||
OpenBSD as they do in Linux. But it *does* work. Here are some advices: | |||||
* Use `cuaXX` instead of `ttyXX`. | |||||
* Run `cu -l /dev/cuaXX` before running your tool and run a dummy command to | |||||
make sure that the output buffer is flushed. | |||||
On Linux, it's generally easier: | |||||
* Run screen on the device (often `/dev/ttyUSBX`) | |||||
* Quit with `CTRL+A :quit` | |||||
* Run the tool on the same device |
@@ -22,13 +22,11 @@ int main(int argc, char **argv) | |||||
fprintf(stderr, "Can't open %s.\n", argv[3]); | fprintf(stderr, "Can't open %s.\n", argv[3]); | ||||
return 1; | return 1; | ||||
} | } | ||||
int fd = open(argv[1], O_RDWR|O_NOCTTY|O_SYNC); | |||||
int fd = ttyopen(argv[1]); | |||||
if (fd < 0) { | if (fd < 0) { | ||||
fprintf(stderr, "Could not open %s\n", argv[1]); | fprintf(stderr, "Could not open %s\n", argv[1]); | ||||
return 1; | return 1; | ||||
} | } | ||||
set_interface_attribs(fd, 0, 0); | |||||
set_blocking(fd, 1); | |||||
char s[0x40]; | char s[0x40]; | ||||
char buf[1024] = {0}; | char buf[1024] = {0}; | ||||
sendcmdp(fd, ": _ 1024 0 DO KEY DUP .x I BLK( + C! LOOP ;"); | sendcmdp(fd, ": _ 1024 0 DO KEY DUP .x I BLK( + C! LOOP ;"); | ||||
@@ -4,18 +4,33 @@ | |||||
#include <errno.h> | #include <errno.h> | ||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <string.h> | #include <string.h> | ||||
#include <fcntl.h> | |||||
#define BREATHE usleep(2000) | |||||
//#define DEBUG(...) fprintf(stderr, __VA_ARGS__) | |||||
#define DEBUG(...) | |||||
void mread(int fd, char *s, int count) | void mread(int fd, char *s, int count) | ||||
{ | { | ||||
while (count) { | while (count) { | ||||
while (read(fd, s, 1) == 0) { | while (read(fd, s, 1) == 0) { | ||||
usleep(1000); | |||||
BREATHE; | |||||
} | } | ||||
s++; | s++; | ||||
count--; | count--; | ||||
} | } | ||||
} | } | ||||
// Make sure that nothing is waiting in the pipeline | |||||
static void mempty(int fd) | |||||
{ | |||||
char c; | |||||
while (read(fd, &c, 1) == 1) { | |||||
DEBUG("Emptying %d\n", c); | |||||
BREATHE; | |||||
} | |||||
} | |||||
static void mexpect(int fd, char ec) | static void mexpect(int fd, char ec) | ||||
{ | { | ||||
char c; | char c; | ||||
@@ -36,19 +51,23 @@ void readprompt(int fd) | |||||
void sendcmd(int fd, char *cmd) | void sendcmd(int fd, char *cmd) | ||||
{ | { | ||||
DEBUG("Sending %s\n", cmd); | |||||
char junk[2]; | char junk[2]; | ||||
while (*cmd) { | while (*cmd) { | ||||
DEBUG("W: %d\n", *cmd); | |||||
write(fd, cmd, 1); | write(fd, cmd, 1); | ||||
BREATHE; | |||||
read(fd, &junk, 1); | read(fd, &junk, 1); | ||||
DEBUG("R: %d\n", *junk); | |||||
cmd++; | cmd++; | ||||
// The other side is sometimes much slower than us and if we don't let | // The other side is sometimes much slower than us and if we don't let | ||||
// it breathe, it can choke. | // it breathe, it can choke. | ||||
usleep(1000); | |||||
BREATHE; | |||||
} | } | ||||
write(fd, "\r", 1); | write(fd, "\r", 1); | ||||
mexpect(fd, '\r'); | mexpect(fd, '\r'); | ||||
mexpect(fd, '\n'); | mexpect(fd, '\n'); | ||||
usleep(1000); | |||||
BREATHE; | |||||
} | } | ||||
// Send a cmd and also read the " ok" prompt | // Send a cmd and also read the " ok" prompt | ||||
@@ -79,6 +98,7 @@ int set_interface_attribs(int fd, int speed, int parity) | |||||
// disable IGNBRK for mismatched speed tests; otherwise receive break | // disable IGNBRK for mismatched speed tests; otherwise receive break | ||||
// as \000 chars | // as \000 chars | ||||
tty.c_iflag &= ~IGNBRK; // disable break processing | tty.c_iflag &= ~IGNBRK; // disable break processing | ||||
tty.c_iflag &= ~ICRNL; // disable CR->NL mapping | |||||
tty.c_lflag = 0; // no signaling chars, no echo, | tty.c_lflag = 0; // no signaling chars, no echo, | ||||
// no canonical processing | // no canonical processing | ||||
tty.c_oflag = 0; // no remapping, no delays | tty.c_oflag = 0; // no remapping, no delays | ||||
@@ -118,3 +138,15 @@ void set_blocking(int fd, int should_block) | |||||
} | } | ||||
} | } | ||||
int ttyopen(char *devname) | |||||
{ | |||||
int fd = 0; | |||||
if (strcmp(devname, "-") != 0) { | |||||
fd = open(devname, O_RDWR|O_NOCTTY|O_SYNC); | |||||
} | |||||
set_interface_attribs(fd, 0, 0); | |||||
set_blocking(fd, 0); | |||||
mempty(fd); | |||||
set_blocking(fd, 1); | |||||
return fd; | |||||
} |
@@ -4,4 +4,4 @@ void mread(int fd, char *s, int count); | |||||
void readprompt(int fd); | void readprompt(int fd); | ||||
int set_interface_attribs(int fd, int speed, int parity); | int set_interface_attribs(int fd, int speed, int parity); | ||||
void set_blocking(int fd, int should_block); | void set_blocking(int fd, int should_block); | ||||
int ttyopen(char *devname); |
@@ -14,12 +14,11 @@ int main(int argc, char **argv) | |||||
fprintf(stderr, "Usage: ./exec device\n"); | fprintf(stderr, "Usage: ./exec device\n"); | ||||
return 1; | return 1; | ||||
} | } | ||||
int fd = open(argv[1], O_RDWR|O_NOCTTY|O_SYNC); | |||||
int fd = ttyopen(argv[1]); | |||||
if (fd < 0) { | if (fd < 0) { | ||||
fprintf(stderr, "Could not open %s\n", argv[1]); | fprintf(stderr, "Could not open %s\n", argv[1]); | ||||
return 1; | return 1; | ||||
} | } | ||||
set_interface_attribs(fd, 0, 0); | |||||
set_blocking(fd, 0); | set_blocking(fd, 0); | ||||
int c = getchar(); | int c = getchar(); | ||||
while (c != EOF) { | while (c != EOF) { | ||||
@@ -27,13 +27,17 @@ int main(int argc, char **argv) | |||||
return 0; | return 0; | ||||
} | } | ||||
int fd = open(argv[1], O_RDWR|O_NOCTTY); | |||||
int fd = ttyopen(argv[1]); | |||||
if (fd < 0) { | |||||
fprintf(stderr, "Could not open %s\n", argv[1]); | |||||
return 1; | |||||
} | |||||
char s[0x30]; | char s[0x30]; | ||||
sprintf(s, ": _ 0x%04x 0x%04x DO I @ .x LOOP ; _", memptr+bytecount, memptr); | sprintf(s, ": _ 0x%04x 0x%04x DO I @ .x LOOP ; _", memptr+bytecount, memptr); | ||||
sendcmd(fd, s); | sendcmd(fd, s); | ||||
for (int i=0; i<bytecount; i++) { | for (int i=0; i<bytecount; i++) { | ||||
read(fd, s, 2); // read hex pair | |||||
mread(fd, s, 2); // read hex pair | |||||
s[2] = 0; // null terminate | s[2] = 0; // null terminate | ||||
unsigned char c = strtol(s, NULL, 16); | unsigned char c = strtol(s, NULL, 16); | ||||
putchar(c); | putchar(c); | ||||
@@ -35,13 +35,11 @@ int main(int argc, char **argv) | |||||
return 1; | return 1; | ||||
} | } | ||||
rewind(fp); | rewind(fp); | ||||
int fd = open(argv[1], O_RDWR|O_NOCTTY|O_SYNC); | |||||
int fd = ttyopen(argv[1]); | |||||
if (fd < 0) { | if (fd < 0) { | ||||
fprintf(stderr, "Could not open %s\n", argv[1]); | fprintf(stderr, "Could not open %s\n", argv[1]); | ||||
return 1; | return 1; | ||||
} | } | ||||
set_interface_attribs(fd, 0, 0); | |||||
set_blocking(fd, 1); | |||||
char s[0x40]; | char s[0x40]; | ||||
sprintf(s, | sprintf(s, | ||||
": _ 0x%04x 0x%04x DO KEY DUP .x I C! LOOP ; _", | ": _ 0x%04x 0x%04x DO KEY DUP .x I C! LOOP ; _", | ||||
@@ -50,8 +48,8 @@ int main(int argc, char **argv) | |||||
int returncode = 0; | int returncode = 0; | ||||
while (fread(s, 1, 1, fp)) { | while (fread(s, 1, 1, fp)) { | ||||
putchar('.'); | |||||
fflush(stdout); | |||||
putc('.', stderr); | |||||
fflush(stderr); | |||||
unsigned char c = s[0]; | unsigned char c = s[0]; | ||||
write(fd, &c, 1); | write(fd, &c, 1); | ||||
usleep(1000); // let it breathe | usleep(1000); // let it breathe | ||||
@@ -69,8 +67,11 @@ int main(int argc, char **argv) | |||||
} | } | ||||
readprompt(fd); | readprompt(fd); | ||||
sendcmdp(fd, "FORGET _"); | sendcmdp(fd, "FORGET _"); | ||||
printf("Done!\n"); | |||||
fprintf(stderr, "Done!\n"); | |||||
fclose(fp); | fclose(fp); | ||||
if (fd > 0) { | |||||
close(fd); | |||||
} | |||||
return returncode; | return returncode; | ||||
} | } | ||||