From 252d709ce24e5544d9a6fc6faea2adf861c957ff Mon Sep 17 00:00:00 2001 From: k Date: Tue, 1 Aug 2023 15:13:18 +0000 Subject: [PATCH] added code --- .gitignore | 2 + mkfile | 14 ++ stm32up.c | 518 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 534 insertions(+) create mode 100644 .gitignore create mode 100644 mkfile create mode 100644 stm32up.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5c2e914 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.out +stm32up.* diff --git a/mkfile b/mkfile new file mode 100644 index 0000000..be07992 --- /dev/null +++ b/mkfile @@ -0,0 +1,14 @@ + +#include + +static int debug = 0; +static uchar buf[256]; + +enum { + Doinfo, + Doread, + Dowrite, + Dogo, + Doreadprot, + Doreadunprot, + Dowriteprot, + Dowriteunprot, + Docsum +}; + +enum Uartcmd { + Nop = 0x00, + Full = 0xFF, + Ack = 0x79, + Nack = 0x1F, + Conninit = 0x7F, + Get = 0x00, + Getversion = 0x01, + Getid = 0x02, + Read = 0x11, + Go = 0x21, + Write = 0x31, + Erase = 0x43, + Eraseext = 0x44, + Special = 0x50, + Specialext = 0x51, + Writeprot = 0x63, + Writeunprot = 0x73, + Readprot = 0x82, + Readunprot = 0x92, + Checksum = 0xA1 // this is not yet implemented +}; + +void +stm_info(int dev) +{ + if(debug) + fprint(2, "acquiring device info\n"); + + // get the protocol version and commands + buf[0] = Get; buf[1] = Full ^ Get; + if(write(dev, buf, 2) < 0) { + fprint(2, "unable to write: %r\n"); + exits("protoerr");; + } + + if(readn(dev, buf, 1) == 0 || buf[0] != Ack) { + fprint(2, "'get' rejected\n"); + exits("protoerr");; + } + if(readn(dev, buf, 14) == 0 || buf[0] != 11 || buf[13] != Ack) { + fprint(2, "protocol error while getting device info\n"); + exits("protoerr");; + } + + fprint(2, "protocol version: %x\n", buf[1]); + + if(debug) { + for(int i = 0; i < 14; i++) + fprint(2, "0x%02x ", buf[i]); + fprint(2, "\n"); + } + + if(buf[2] != Get || + buf[3] != Getversion || + buf[4] != Getid || + buf[5] != Read || + buf[6] != Go || + buf[7] != Write || + (buf[8] != Erase && buf[8] != Eraseext) || + buf[9] != Writeprot || + buf[10] != Writeunprot || + buf[11] != Readprot || + buf[12] != Readunprot) { + fprint(2, "command code mismatch, run with -d\n"); + return; + } + + // get the device id + if(debug) + fprint(2, "getting device id\n"); + buf[0] = Getid; buf[1] = Full ^ Getid; + if(write(dev, buf, 2) < 0) { + fprint(2, "unable to write\n"); + exits("protoerr");; + } + + if(readn(dev, buf, 1) == 0 || buf[0] != Ack) { + fprint(2, "'get id' command rejected\n"); + exits("protoerr");; + } + if(readn(dev, buf, 4) == 0 || buf[0] != 1 || buf[3] != Ack) { + fprint(2, "protocol error while getting device id\n"); + exits("protoerr");; + } + + fprint(2, "device id: %x%x\n", buf[1], buf[2]); +} + +void +stm_protect(int dev, int acmd) +{ + char *cmds; + int cmd; + + switch(acmd) { + case Doreadprot: cmd = Readprot; cmds = "read protect"; break; + case Doreadunprot: cmd = Readunprot; cmds = "read unprotect"; break; + case Dowriteunprot: cmd = Writeunprot; cmds = "write unprotect"; break; + default: + fprint(2, "stm_protect does not handle this command\n"); + exits("apperr"); + } + + if(debug) + fprint(2, "%s device\n", cmds); + + buf[0] = cmd; buf[1] = Full ^ cmd; + if(write(dev, buf, 2) < 0) { + fprint(2, "unable to write\n"); + exits("protoerr");; + } + + if(readn(dev, buf, 1) == 0 || buf[0] != Ack) { + fprint(2, "'%s' command rejected\n", cmds); + exits("protoerr");; + } + + buf[0] = Ack; + if(write(dev, buf, 1) < 0) { + fprint(2, "unable to ack %s", cmds); + exits("protoerr");; + } + + if(readn(dev, buf, 1) == 0 || buf[0] != Ack) { + fprint(2, "'%s' unable to ack\n", cmds); + exits("protoerr");; + } + + fprint(2, "%s done\n", cmds); +} + +void +stm_readpage(int dev, uvlong addr, uchar sz) // size - 1 +{ + if(addr + (sz + 1) < addr) { + fprint(2, "addr + sz < addr; please check values\n"); + exits("protoerr"); + } + + buf[0] = Read; buf[1] = Full ^ Read; + if(write(dev, buf, 2) < 0) { + fprint(2, "unable to write\n"); + exits("protoerr"); + } + + if(readn(dev, buf, 1) == 0 || buf[0] != Ack) { + fprint(2, "'read memory' command rejected\n"); + exits("protoerr"); + } + + // send the start address + buf[0] = (addr >> 24) & 0xFF; + buf[1] = (addr >> 16) & 0xFF; + buf[2] = (addr >> 8) & 0xFF; + buf[3] = addr & 0xFF; + buf[4] = buf[0] ^ buf[1] ^ buf[2] ^ buf[3]; + + if(write(dev, buf, 5) < 0) { + fprint(2, "unable to write\n"); + exits("protoerr"); + } + + if(readn(dev, buf, 1) == 0 || buf[0] != Ack) { + fprint(2, "read memory address rejected\n"); + exits("protoerr"); + } + + // send the size + buf[0] = sz; buf[1] = Full ^ buf[0]; + + if(write(dev, buf, 2) < 0) { + fprint(2, "unable to write\n"); + exits("protoerr"); + } + + if(readn(dev, buf, 1) == 0 || buf[0] != Ack) { + fprint(2, "read command rejected; check address and count\n"); + exits("protoerr"); + } + + // read contents + int c = readn(dev, buf, sz + 1); + if(c != sz + 1) { + fprint(2, "memory read error, address 0x%08llx, size-1 0x%02x, c %d\n", addr, sz, c); + exits("apperr"); + } + write(1, buf, c); +} + +void +stm_writepage(int dev, uvlong addr, uchar sz) // size - 1 +{ + if(addr + (sz + 1) < addr) { + fprint(2, "addr + sz < addr; please check values\n"); + exits("protoerr"); + } + + buf[0] = Write; buf[1] = Full ^ Write; + if(write(dev, buf, 2) < 0) { + fprint(2, "unable to write\n"); + exits("protoerr"); + } + + if(readn(dev, buf, 1) == 0 || buf[0] != Ack) { + fprint(2, "'write memory' command rejected\n"); + exits("protoerr"); + } + + // send the start address + buf[0] = (addr >> 24) & 0xFF; + buf[1] = (addr >> 16) & 0xFF; + buf[2] = (addr >> 8) & 0xFF; + buf[3] = addr & 0xFF; + buf[4] = buf[0] ^ buf[1] ^ buf[2] ^ buf[3]; + + if(write(dev, buf, 5) < 0) { + fprint(2, "unable to write\n"); + exits("protoerr"); + } + + if(readn(dev, buf, 1) == 0 || buf[0] != Ack) { + fprint(2, "write memory address rejected\n"); + exits("protoerr"); + } + + // send the size + buf[0] = sz; buf[1] = Full ^ buf[0]; + + if(write(dev, buf, 2) < 0) { + fprint(2, "unable to write\n"); + exits("protoerr"); + } + + if(readn(dev, buf, 1) == 0 || buf[0] != Ack) { + fprint(2, "write command rejected; check address and count\n"); + exits("protoerr"); + } + + // write contents + int c = readn(0, buf, sz + 1); + if(c != sz + 1) { + fprint(2, "memory write error, address 0x%08llx, size-1 0x%02x, c %d\n", addr, sz, c); + exits("apperr"); + } + write(dev, buf, c); +} + +void +stm_read(int dev, uvlong addr, uvlong sz) +{ + if(sz == 0) { + fprint(2, "read size cannot be 0\n"); + exits("protoerr"); + } + if(addr + sz < addr) { + fprint(2, "addr + sz < addr; please check values\n"); + exits("protoerr"); + } + + + fprint(2, "reading device memory 0x%08llx, size: 0x%08llx\n", addr, sz); + + // start read memory command + uvlong caddr = addr; + uvlong csz = sz; + + while(caddr < (addr + sz)) { + uchar rsz = 0xFF; + if(csz < 0x100) + rsz = csz - 1; + + stm_readpage(dev, caddr, rsz); + + caddr = caddr + (rsz + 1); + csz = csz - (rsz + 1); + } + + fprint(2, "memory read\n"); +} + +void +stm_write(int dev, uvlong addr, uvlong sz) +{ + if(sz == 0) { + fprint(2, "write size cannot be 0\n"); + exits("protoerr"); + } + if(addr + sz < addr) { + fprint(2, "addr + sz < addr; please check values\n"); + exits("protoerr"); + } + + fprint(2, "writing device memory 0x%08llx, size: 0x%08llx\n", addr, sz); + + // start read memory command + uvlong caddr = addr; + uvlong csz = sz; + + while(caddr < (addr + sz)) { + uchar rsz = 0xFF; + if(csz < 0x100) + rsz = csz - 1; + + stm_writepage(dev, caddr, rsz); + + caddr = caddr + (rsz + 1); + csz = csz - (rsz + 1); + } + + fprint(2, "memory written\n"); +} + +void +stm_go(int dev, uvlong addr) +{ + if(debug) + fprint(2, "device requested to jump to 0x%08llx\n", addr); + + // get the protocol version and commands + buf[0] = Go; buf[1] = Full ^ Go; + if(write(dev, buf, 2) < 0) { + fprint(2, "unable to write: %r\n"); + exits("protoerr");; + } + + if(readn(dev, buf, 1) == 0 || buf[0] != Ack) { + fprint(2, "'go' rejected\n"); + exits("protoerr");; + } + + // send the start address + buf[0] = (addr >> 24) & 0xFF; + buf[1] = (addr >> 16) & 0xFF; + buf[2] = (addr >> 8) & 0xFF; + buf[3] = addr & 0xFF; + buf[4] = buf[0] ^ buf[1] ^ buf[2] ^ buf[3]; + + if(write(dev, buf, 5) < 0) { + fprint(2, "unable to write\n"); + exits("protoerr"); + } + + if(readn(dev, buf, 1) == 0 || buf[0] != Ack) { + fprint(2, "go address rejected\n"); + exits("protoerr"); + } + + fprint(2, "device jumped to 0x%08llx\n", addr); +} + +void +stm_checksum(int dev) +{ +} + +void +usage(void) +{ + fprint(2, "usage: %s [-d] [-D device] command args ..\n", argv0); + fprint(2, " info\n"); + fprint(2, " read addr size\n"); + fprint(2, " write addr size\n"); + fprint(2, " go addr\n"); + fprint(2, " readp, readunp, writeunp\n"); + fprint(2, " TODO: writep,csum\n"); + exits("usage"); +} + +void +main(int argc, char **argv) +{ + char* devpath = "/dev/eia0"; + int action = -1; + int dev = -1; + + uvlong addr = 0; + uvlong sz = 0; + + ARGBEGIN { + case 'd': + debug = 1; + break; + case 'D': + devpath = EARGF(usage()); + break; + default: usage(); + } ARGEND + + if(argv[0] == 0) + usage(); + + if(!strcmp(argv[0], "info")) + action = Doinfo; + if(!strcmp(argv[0], "read")) { + if(argv[1] == 0 || argv[2] == 0) + usage(); + addr = strtoull(argv[1], nil, 16); + sz = strtoull(argv[2], nil, 16); + action = Doread; + } + if(!strcmp(argv[0], "write")) { + if(argv[1] == 0 || argv[2] == 0) + usage(); + addr = strtoull(argv[1], nil, 16); + sz = strtoull(argv[2], nil, 16); + action = Dowrite; + } + if(!strcmp(argv[0], "go")) { + if(argv[1] == 0) + usage(); + addr = strtoull(argv[1], nil, 16); + action = Dogo; + } + if(!strcmp(argv[0], "readp")) + action = Doreadprot; + if(!strcmp(argv[0], "readunp")) + action = Doreadunprot; + if(!strcmp(argv[0], "writeunp")) + action = Doreadunprot; + if(!strcmp(argv[0], "csum")) + action = Docsum; + if(action < 0) + usage(); + + // set serial operating parameters + if(debug) + fprint(2, "setting modem to 9600 8E1\n"); + int devctl = open(smprint("%sctl", devpath), OWRITE); + if(devctl < 0) { + fprint(2, "unable to open device ctl %sctl: %r\n", devpath); + exits("deverr"); + } + + if(write(devctl, "b9600\n", 8) < 0) { + fprint(2, "error: unable to set serial baud: %r\n"); + exits("deverr"); + } + if(write(devctl, "l8\n", 3) < 0) { + fprint(2, "error: unable to set serial length: %r\n"); + exits("deverr"); + } + if(write(devctl, "pe\n", 3) < 0) { + fprint(2, "error: unable to set serial parity: %r\n"); + exits("deverr"); + } + if(write(devctl, "s1\n", 3) < 0) { + fprint(2, "error: unable to set serial stop bits: %r\n"); + exits("deverr"); + } + if(write(devctl, "f\n", 3) < 0) { + fprint(2, "error: unable to flush the serial line: %r\n"); + exits("deverr"); + } + + if(debug) + fprint(2, "modem set up accordingly\n"); + + // opening serial line + if(debug) + fprint(2, "opening %s\n", devpath); + dev = open(devpath, ORDWR); + if(dev < 0) { + fprint(2, "unable to open device %s: %r\n", devpath); + exits("deverr"); + } + + // initiate connection; send Conninit, and wait for Ack + if(debug) + fprint(2, "initiating connection\n"); + buf[0] = Conninit; + if(write(dev, buf, 1) < 0) { + fprint(2, "error writing while initiating\n"); + exits("connerr"); + } + + if(readn(dev, buf, 1) <= 0 || buf[0] != Ack) { + fprint(2, "connection could not be initiated, got %x\n", buf[0]); + exits("connerr"); + } + + // handle action + switch(action) { + case Doinfo: stm_info(dev); break; + case Doread: stm_read(dev, addr, sz); break; + case Dowrite: stm_write(dev, addr, sz); break; + case Doreadprot: + case Doreadunprot: + case Dowriteunprot: + stm_protect(dev, action); break; + case Dogo: stm_go(dev, addr); break; + case Docsum: stm_checksum(dev); break; + default: exits("apperr"); + } + + if(debug) + fprint(2, "exiting\n"); + + exits(nil); +}