diff options
Diffstat (limited to 'util')
| -rw-r--r-- | util/nvmutil/nvmutil.c | 114 |
1 files changed, 68 insertions, 46 deletions
diff --git a/util/nvmutil/nvmutil.c b/util/nvmutil/nvmutil.c index 256c3b88..c5611257 100644 --- a/util/nvmutil/nvmutil.c +++ b/util/nvmutil/nvmutil.c @@ -18,10 +18,11 @@ void cmd_setchecksum(void), cmd_brick(void), swap(int partnum), writeGbe(void), cmd_dump(void), cmd_setmac(void), readGbe(void), print_mac_address(int), hexdump(int), set_mac_nib(int, int, uint8_t *), checkdir(const char *), parseMacString(const char *strMac, uint16_t *mac), cmd_swap(void), - openFiles(void), cmd_copy(void), writeGbe_part(int), readGbe_part(int), + openFiles(void), cmd_copy(void), writeGbe_part(int), readGbe_part(int, int), set_cmd(int, char **), setWord(int, int, uint16_t), check_bounds(int, int), - xopen (int *, const char *, int p, struct stat *), checkMacSeparator(int), - set_mac_byte(int, uint64_t *), usage(char*), set_io_flags(int, char **); + xopen(int *, const char *, int p, struct stat *), checkMacSeparator(int), + set_mac_byte(int, uint64_t *), usage(char*), set_io_flags(int, char **), + err_if(int); int goodChecksum(int partnum), write_mac_part(int), set_err(int); uint8_t hextonum(char chs), rhex(void); uint16_t word(int, int); @@ -41,9 +42,10 @@ uint16_t word(int, int); uint8_t buf[SIZE_8KB]; uint16_t mac[3] = {0, 0, 0}; size_t partsize; -int flags, rfd, fd, part, e = 1; +int flags, rfd, fd, part, e = 1, invert = 0; +int nvmPartModified[2] = {0, 0}; -const char *strMac = NULL, *strRMac = "xx:xx:xx:xx:xx:xx", *fname = NULL; +const char *strMac = NULL, *strRMac = "xx:xx:xx:xx:xx:xx", *fname = ""; typedef struct op { char *str; @@ -60,8 +62,6 @@ op_t op[] = { }; void (*cmd)(void) = NULL; -#define err_if(x) if (x) err(set_err(ECANCELED), "%s", fname) - int main(int argc, char *argv[]) { @@ -93,7 +93,7 @@ main(int argc, char *argv[]) writeGbe(); err_if((errno != 0) && (cmd != cmd_dump)); - return errno ? 1 : 0; + return errno ? EXIT_FAILURE : EXIT_SUCCESS; } void @@ -140,24 +140,15 @@ set_io_flags(int argc, char *argv[]) } void -checkdir(const char *path) -{ - if (opendir(path) != NULL) - err(set_err(EISDIR), "%s", path); - if (errno == ENOTDIR) - errno = 0; - err_if(errno); -} - -void openFiles(void) { struct stat st; + struct stat st_rfd; checkdir("/dev/urandom"); checkdir(fname); - xopen(&rfd, "/dev/urandom", O_RDONLY, &st); + xopen(&rfd, "/dev/urandom", O_RDONLY, &st_rfd); xopen(&fd, fname, flags, &st); switch(st.st_size) { @@ -173,28 +164,52 @@ openFiles(void) } void +checkdir(const char *path) +{ + struct stat st; + if (stat(path, &st) == -1) + err(set_err(ECANCELED), "%s", path); + if (S_ISDIR(st.st_mode)) + err(set_err(EISDIR), "%s", path); +} + +void xopen(int *f, const char *l, int p, struct stat *st) { - if ((*f = open(l, p)) == -1) \ - err(set_err(ECANCELED), "%s", l); \ - if (fstat(*f, st) == -1) \ - err(set_err(ECANCELED), "%s", l); + if ((*f = open(l, p)) == -1) + err(set_err(ECANCELED), "%s", l); + if (fstat(*f, st) == -1) + err(set_err(ECANCELED), "%s", l); } void readGbe(void) { + int do_read[2] = {1, 1}; + + if ((cmd == cmd_copy) || (cmd == cmd_brick) || (cmd == cmd_setchecksum)) + do_read[part ^ 1] = 0; + + /* + * speedhack: if copy/swap, flip where data gets written to memory, + * so that cmd_copy and cmd_swap don't have to work on every word + */ + if ((cmd == cmd_copy) || (cmd == cmd_swap)) + invert = 1; + for (int p = 0; p < 2; p++) - readGbe_part(p); + if (do_read[p]) + readGbe_part(p, invert); } void -readGbe_part(int p) +readGbe_part(int p, int invert) { - if (pread(fd, buf + (SIZE_4KB * p), SIZE_4KB, p * partsize) != SIZE_4KB) + if (pread(fd, buf + (SIZE_4KB * (p ^ invert)), SIZE_4KB, p * partsize) + != SIZE_4KB) err(set_err(ECANCELED), "Can't read %d b from '%s' p%d", SIZE_4KB, fname, p); - swap(p); /* handle big-endian host CPU */ + swap(p ^ invert); /* handle big-endian host CPU */ } void @@ -287,14 +302,15 @@ rhex(void) { static uint8_t n = 0, rnum[16]; if (!n) - err_if(pread(rfd, (uint8_t *) &rnum, (n = 15) + 1, 0) == -1); + err_if(read(rfd, (uint8_t *) &rnum, (n = 15) + 1) == -1); return rnum[n--] & 0xf; } int write_mac_part(int partnum) { - if (!goodChecksum(part = partnum)) + part = partnum; + if (!goodChecksum(partnum)) return 0; for (int w = 0; w < 3; w++) @@ -310,17 +326,19 @@ write_mac_part(int partnum) void cmd_dump(void) { - for (int partnum = 0, numInvalid = 0; partnum < 2; partnum++) { + int numInvalid = 0; + + for (int partnum = 0; partnum < 2; partnum++) { if (!goodChecksum(partnum)) ++numInvalid; printf("MAC (part %d): ", partnum); print_mac_address(partnum); hexdump(partnum); - - if ((numInvalid < 2) && (partnum)) - errno = 0; } + + if ((numInvalid < 2)) + errno = 0; } void @@ -372,9 +390,8 @@ cmd_brick(void) void cmd_copy(void) { - err_if(!goodChecksum(part)); - for (int c = 0; c < (SIZE_4KB >> 1); c++) - setWord(c, part ^ 1, word(c, part)); + err_if(!goodChecksum(part ^ 1)); + nvmPartModified[part ^ 1] = 1; } void @@ -382,11 +399,7 @@ cmd_swap(void) { err_if(!(goodChecksum(0) || goodChecksum(1))); errno = 0; - for (int c = 0; c < (SIZE_4KB >> 1); c++) { - uint16_t chg = word(c, 0); - setWord(c, 0, word(c, 1)); - setWord(c, 1, chg); - } + nvmPartModified[1] = nvmPartModified[0] = 1; } int @@ -399,7 +412,7 @@ goodChecksum(int partnum) if (total == NVM_CHECKSUM) return 1; - fprintf(stderr, "WARNING: BAD checksum in part %d\n", partnum); + fprintf(stderr, "WARNING: BAD checksum in part %d\n", partnum ^ invert); (void) set_err(ECANCELED); return 0; } @@ -415,6 +428,7 @@ void setWord(int pos16, int p, uint16_t val16) { check_bounds(pos16, p); + nvmPartModified[p] = 1; ((uint16_t *) (buf + (SIZE_4KB * p)))[pos16] = val16; } @@ -432,7 +446,8 @@ writeGbe(void) { if (flags != O_RDONLY) for (int p = 0; p < 2; p++) - writeGbe_part(p); + if (nvmPartModified[p]) + writeGbe_part(p); err_if(close(fd) == -1); } @@ -453,8 +468,8 @@ swap(int partnum) for (size_t w = NVM_SIZE * ((uint8_t *) &e)[0], x = 1; w < NVM_SIZE; w += 2, x += 2) { uint8_t chg = n[w]; - n[w] ^= n[x]; - n[x] ^= chg; + n[w] = n[x]; + n[x] = chg; } } @@ -478,9 +493,16 @@ usage(char *util) err(set_err(ECANCELED), "Too few arguments"); } +void +err_if(int x) +{ + if (x) + err(set_err(ECANCELED), "%s", fname); +} + int set_err(int x) { errno = errno ? errno : x; - return 1; + return EXIT_FAILURE; } |
