add checksum bit to ecp Reference: /n/atom/patch/applied2013/ecpfix Date: Wed Jun 19 01:54:56 CES 2013 Signed-off-by: quanstro@quanstro.net --- /sys/src/cmd/ecp.c Wed Jun 19 01:54:42 2013 +++ /sys/src/cmd/ecp.c Wed Jun 19 01:54:42 2013 @@ -168,6 +168,39 @@ repos(fp, 0); } +static char magic[] = "\235any old ☺ rubbish\173"; +static char uniq[sizeof magic + 2*sizeof(ulong)]; + +/* + * generate magic + unique string, add to start & end of buff. + * return tail pointer. + */ +static char * +addmagic(char *buff, int bytes) +{ + char *tail; + uchar *p; + static ulong seq; + + strcpy(uniq, magic); + p = (uchar*)uniq + sizeof magic - 1; + putbe(p, time(0), 4); + putbe(p+4, ++seq, 4); + + memcpy(buff, uniq, sizeof uniq); + tail = buff + bytes - sizeof uniq; + memcpy(tail, uniq, sizeof uniq); + return tail; +} + +/* verify magic + unique strings in buff */ +static int +ismagicok(char *buff, char *tail) +{ + return memcmp(buff, uniq, sizeof uniq) == 0 || + memcmp(tail, uniq, sizeof uniq) == 0; +} + /* * transfer (many) sectors. reblock input as needed. * returns Enone if no failures, others on failure with errstr set. @@ -176,6 +209,7 @@ bio(File *fp, Rdwrfn *rdwr, char *buff, Daddr stsect, int sects, int mustseek) { int xfered; + char *tail; ulong toread, bytes = sects * sectsz; static int reblocked = 0; @@ -188,12 +222,21 @@ if ((long)blocksize != blocksize || (long)bytes != bytes) sysfatal("i/o count too big: %lud", bytes); + SET(tail); + if (rdwr == read) + tail = addmagic(buff, bytes); werrstr(""); xfered = (*rdwr)(fp->fd, buff, bytes); - if (xfered == bytes) + if (xfered == bytes) { + /* don't trust the hardware; it may lie */ + if (rdwr == read && ismagicok(buff, tail)) + fprint(2, "%s: `good' read didn't change buffer\n", + argv0); return Enone; /* did as we asked */ + } if (xfered < 0) return Eio; /* out-and-out i/o error */ + /* * Kernel transferred less than asked. Shouldn't happen; * probably indicates disk driver error or trying to @@ -201,6 +244,7 @@ * I/O error that reads zeros past the point of error, * unless reblocking input and this is a read. */ + if (rdwr == write) return Eio; if (!reblock) {