#include #include #include #include #include #include #include #include static int fd = -1; void int_handler(int dummy) { write(STDERR_FILENO, "sigint\n", 7); if (fd != -1) close(fd); exit(1); } void set_attrs(int fd) { struct termios t; int attr = tcgetattr(fd, &t); assert (attr != -1); cfsetospeed(&t, B115200); cfsetispeed(&t, B115200); t.c_cflag = (t.c_cflag & ~CSIZE) | CS8; // 8-bit chars t.c_lflag = 0; // no signaling chars, no echo, no canonical processing t.c_oflag = 0; // no remapping, no delays t.c_cc[VMIN] = 1; // read doesn't block t.c_cc[VTIME] = 0; // no timeout // convert break to null byte, no CR to NL translation, // no NL to CR translation, don't mark parity errors or breaks // no input parity check, don't strip high bit off, // no XON/XOFF software flow control t.c_iflag &= ~(IGNBRK | BRKINT | ICRNL | INLCR | PARMRK | INPCK | ISTRIP | IXOFF | IXON | IXANY); t.c_cflag |= (CLOCAL | CREAD); // ignore modem controls, enable reading t.c_cflag &= ~(PARENB | PARODD); // shut off parity t.c_cflag &= ~CSTOPB; // one stop bit t.c_cflag |= CRTSCTS; // enable CTS/RTS int ret = tcsetattr(fd, TCSANOW, &t); assert (ret != -1); } ssize_t write_block(int fd, char * buf, size_t len) { ssize_t wret, rret; size_t out_len = 0; char in_buf[len]; memset(in_buf, 0xea, len); #define BLOCK_SIZE 8 for (unsigned int i = 0; i < (len / BLOCK_SIZE); i++) { wret = write(fd, &buf[BLOCK_SIZE * i], BLOCK_SIZE); assert (wret == BLOCK_SIZE); int tret = tcdrain(fd); assert (tret != -1); //printf("%x\n", out_buf[BLOCK_SIZE * i] & 0xff, rret); size_t block = 0; while (block != BLOCK_SIZE) { rret = read(fd, &in_buf[(BLOCK_SIZE * i) + block], BLOCK_SIZE - block); assert (rret != -1); block += rret; } //printf("%x %x %ld\n", out_buf[BLOCK_SIZE * i] & 0xff, in_buf[BLOCK_SIZE * i] & 0xff, rret); assert (block == BLOCK_SIZE); out_len += block; write(STDERR_FILENO, ".", 1); fsync(STDERR_FILENO); } size_t rem = len % BLOCK_SIZE; if (rem) { wret = write(fd, &buf[len - rem], rem); assert (wret != -1); assert ((size_t)wret == rem); int tret = tcdrain(fd); assert (tret != -1); size_t block = 0; while (block != rem) { rret = read(fd, &in_buf[len - rem + block], rem - block); assert (rret != -1); block += rret; } //printf("%x %x %ld\n", buf[BLOCK_SIZE * i] & 0xff, in_buf[BLOCK_SIZE * i] & 0xff, rret); assert (block == rem); out_len += block; write(STDERR_FILENO, ".", 1); fsync(STDERR_FILENO); } write(STDERR_FILENO, "\n", 1); //int cmp = memcmp(buf, in_buf, len); for (unsigned int bx = 0; bx < len; bx++) { if (buf[bx] != in_buf[bx]) { fprintf(stderr, "buf[%d] != in_buf[%d]\n", bx, bx); fprintf(stderr, "%02x != %02x\n", buf[bx], in_buf[bx]); } } return out_len; } void write_header(int fd, size_t len, size_t addr) { assert (addr <= 0xffff); assert (len <= 255); fprintf(stderr, "len %ld addr %lx\n", len, addr & 0xffff); char out_buf[3] = { len & 0xff, (addr >> 0) & 0xff, (addr >> 8) & 0xff, }; ssize_t wret = write(fd, out_buf, 3); assert (wret != -1); size_t hdr_len = len == 0 ? 2 : 3; char in_buf[3]; size_t offset = 0; ssize_t rret; while (offset != hdr_len) { rret = read(fd, &in_buf[offset], hdr_len - offset); assert (rret != -1); offset += rret; } assert (offset == hdr_len); int cmp = memcmp(in_buf, "LDR", hdr_len); assert (cmp == 0); } static char read_buf[0x8000]; int main(int argc, char *argv[]) { signal(SIGINT, int_handler); int tfd = open("/dev/ttyUSB0", O_RDWR | O_SYNC | O_NOCTTY); assert (tfd != -1); set_attrs(tfd); int tret = tcflush(tfd, TCIOFLUSH); assert (tret != -1); assert (argc > 1); fprintf(stderr, "%s\n", argv[1]); int ffd = open(argv[1], O_RDONLY); ssize_t rret = read(ffd, read_buf, 0x8000); assert (rret != -1 && rret > 0 && rret <= 0x8000); size_t offset = 0; size_t base_address = 0x200; while (rret - offset > 0) { size_t block_len = rret - offset >= 255 ? 255 : rret - offset; write_header(tfd, block_len, base_address + offset); ssize_t block_ret = write_block(tfd, &read_buf[offset], block_len); assert (block_ret != -1); assert ((size_t)block_ret == block_len); offset += block_ret; } fprintf(stderr, "jump %lx\n", base_address & 0xffff); write_header(tfd, 0, base_address); close(fd); } // stty -F /dev/ttyUSB0 115200 -icrnl -imaxbel -opost -onlcr -isig -echo -icanon -ixon