tools: improve usability on OpenBSD

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...
This commit is contained in:
Virgil Dupras 2020-07-02 11:36:53 -04:00
parent a8302920cb
commit c2b507eaff
7 changed files with 79 additions and 17 deletions

28
tools/README.md Normal file
View File

@ -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

View File

@ -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 ;");

View File

@ -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;
}

View File

@ -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);

View File

@ -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) {

View File

@ -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);

View File

@ -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('.'); putc('.', stderr);
fflush(stdout); 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;
} }