summaryrefslogtreecommitdiff
path: root/util
diff options
context:
space:
mode:
Diffstat (limited to 'util')
-rw-r--r--util/nvmutil/nvmutil.c114
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;
}