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:
parent
a8302920cb
commit
c2b507eaff
28
tools/README.md
Normal file
28
tools/README.md
Normal 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
|
@ -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('.');
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user