util/nvmutil: more cleanup
spread out a few lines, so that they are more readable, and more thoroughly comment some parts. Signed-off-by: Leah Rowe <leah@libreboot.org>master
parent
e6f4d11c5e
commit
dc376cca14
|
@ -82,11 +82,13 @@ main(int argc, char *argv[])
|
|||
fprintf(stderr, " %s FILE setchecksum 0|1\n", argv[0]);
|
||||
err(errno = ECANCELED, "Too few arguments");
|
||||
}
|
||||
|
||||
filename = argv[1];
|
||||
if (strcmp(COMMAND, "dump") == 0)
|
||||
flags = O_RDONLY; /* write not needed for dump cmd */
|
||||
else
|
||||
flags = O_RDWR;
|
||||
filename = argv[1];
|
||||
|
||||
/* Err if files are actually directories; this also
|
||||
prevents unveil allowing directory accesses, which
|
||||
is critical because we only want *file* accesses. */
|
||||
|
@ -104,8 +106,8 @@ main(int argc, char *argv[])
|
|||
err_if(pledge("stdio rpath wpath", NULL) == -1);
|
||||
}
|
||||
#endif
|
||||
/* open files, but don't read yet; do pledge after, *then* read */
|
||||
openFiles(filename);
|
||||
|
||||
openFiles(filename); /* open files first, to allow harder pledge: */
|
||||
#ifdef __OpenBSD__
|
||||
/* OpenBSD sandboxing: https://man.openbsd.org/pledge.2 */
|
||||
err_if(pledge("stdio", NULL) == -1);
|
||||
|
@ -115,9 +117,10 @@ main(int argc, char *argv[])
|
|||
if (strcmp(COMMAND, op[i].str) == 0)
|
||||
if ((cmd = argc >= op[i].args ? op[i].cmd : NULL))
|
||||
break; /* function ptr set, as per user cmd */
|
||||
if (cmd == cmd_setmac) { /* user wishes to set the MAC address */
|
||||
strMac = strRMac; /* random mac */
|
||||
if (argc > 3) /* user-supplied mac (can be random) */
|
||||
|
||||
if (cmd == cmd_setmac) {
|
||||
strMac = strRMac; /* random MAC */
|
||||
if (argc > 3) /* user-supplied MAC (can be random) */
|
||||
strMac = MAC_ADDRESS;
|
||||
} else if ((cmd != NULL) && (argc > 3)) { /* user-supplied partnum */
|
||||
err_if((errno = (!((part = PARTN[0] - '0') == 0 || part == 1))
|
||||
|
@ -130,6 +133,7 @@ main(int argc, char *argv[])
|
|||
|
||||
if ((gbeFileChanged) && (flags != O_RDONLY) && (cmd != writeGbe))
|
||||
writeGbe(); /* not called for swap cmd; swap calls writeGbe */
|
||||
|
||||
err_if((errno != 0) && (cmd != cmd_dump)); /* don't err on dump */
|
||||
return errno; /* errno can be set by the dump command */
|
||||
}
|
||||
|
@ -154,7 +158,9 @@ void
|
|||
openFiles(const char *path)
|
||||
{
|
||||
struct stat st;
|
||||
xopen(fd, path, flags);
|
||||
|
||||
xopen(fd, path, flags); /* gbe file */
|
||||
|
||||
switch(st.st_size) {
|
||||
case SIZE_8KB:
|
||||
case SIZE_16KB:
|
||||
|
@ -165,6 +171,8 @@ openFiles(const char *path)
|
|||
err(errno = ECANCELED, "Invalid file size (not 8/16/128KiB)");
|
||||
break;
|
||||
}
|
||||
|
||||
/* the MAC address randomiser relies on reading urandom */
|
||||
xopen(rfd, "/dev/urandom", O_RDONLY);
|
||||
}
|
||||
|
||||
|
@ -173,15 +181,21 @@ void
|
|||
readGbe(void)
|
||||
{
|
||||
if ((cmd == writeGbe) || (cmd == cmd_copy))
|
||||
nf = partsize;
|
||||
nf = partsize; /* read/write the entire block */
|
||||
else
|
||||
nf = 128;
|
||||
skipread[part ^ 1] = (cmd == cmd_copy) | (cmd == cmd_setchecksum)
|
||||
| (cmd == cmd_brick);
|
||||
gbe[1] = (gbe[0] = (size_t) buf) + partsize;
|
||||
nf = 128; /* only read/write the nvm part of the block */
|
||||
|
||||
if ((cmd == cmd_copy) || (cmd == cmd_setchecksum) || (cmd == cmd_brick))
|
||||
skipread[part ^ 1] = 1; /* only read the user-specified part */
|
||||
|
||||
/* we pread per-part, so each part has its own pointer: */
|
||||
gbe[0] = (size_t) buf;
|
||||
gbe[1] = gbe[0] + partsize;
|
||||
|
||||
for (int p = 0; p < 2; p++) {
|
||||
if (skipread[p])
|
||||
continue;
|
||||
continue; /* avoid unnecessary reads */
|
||||
|
||||
err_if(pread(fd, (uint8_t *) gbe[p], nf, p * partsize) == -1);
|
||||
swap(p); /* handle big-endian host CPU */
|
||||
}
|
||||
|
@ -193,12 +207,15 @@ cmd_setmac(void)
|
|||
{
|
||||
if (macAddress(strMac, mac))
|
||||
err(errno = ECANCELED, "Bad MAC address");
|
||||
|
||||
for (int partnum = 0; partnum < 2; partnum++) {
|
||||
if (!goodChecksum(part = partnum))
|
||||
continue;
|
||||
for (int w = 0; w < 3; w++)
|
||||
|
||||
for (int w = 0; w < 3; w++) /* write MAC to gbe part */
|
||||
setWord(w, partnum, mac[w]);
|
||||
cmd_setchecksum();
|
||||
|
||||
cmd_setchecksum(); /* MAC updated; need valid checksum */
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -207,23 +224,33 @@ int
|
|||
macAddress(const char *strMac, uint16_t *mac)
|
||||
{
|
||||
uint64_t total = 0;
|
||||
if (strnlen(strMac, 20) == 17) {
|
||||
if (strnlen(strMac, 20) != 17)
|
||||
return 1; /* 1 means error */
|
||||
|
||||
for (uint8_t h, i = 0; i < 16; i += 3) {
|
||||
if (i != 15)
|
||||
if (strMac[i + 2] != ':')
|
||||
return 1;
|
||||
|
||||
int byte = i / 3;
|
||||
|
||||
/* Update MAC buffer per-nibble from a given string */
|
||||
for (int nib = 0; nib < 2; nib++, total += h) {
|
||||
if ((h = hextonum(strMac[i + nib])) > 15)
|
||||
return 1;
|
||||
if ((byte == 0) && (nib == 1))
|
||||
if (strMac[i + nib] == '?')
|
||||
return 1; /* invalid character, MAC string */
|
||||
|
||||
/* if random: ensure local-only, unicast MAC */
|
||||
if ((byte == 0) && (nib == 1)) /* unicast/local nib */
|
||||
if (strMac[i + nib] == '?') /* ?=random */
|
||||
h = (h & 0xE) | 2; /* local, unicast */
|
||||
|
||||
mac[byte >> 1] |= ((uint16_t ) h)
|
||||
<< ((8 * (byte % 2)) + (4 * (nib ^ 1)));
|
||||
}
|
||||
}}
|
||||
return ((total == 0) | (mac[0] & 1)); /* multicast/all-zero banned */
|
||||
}
|
||||
|
||||
/* do not permit multicast/all-zero MAC: */
|
||||
return ((total == 0) || (mac[0] & 1)) ? 1 : 0;
|
||||
}
|
||||
|
||||
/* convert hex char to char value (0-15) */
|
||||
|
@ -300,7 +327,8 @@ cmd_setchecksum(void)
|
|||
uint16_t val16 = 0;
|
||||
for (int c = 0; c < 0x3F; c++)
|
||||
val16 += word(c, part);
|
||||
setWord(0x3F, part, NVM_CHECKSUM - val16);
|
||||
|
||||
setWord(0x3F, part, NVM_CHECKSUM - val16); /* correct the checksum */
|
||||
}
|
||||
|
||||
/* intentionally set wrong checksum on part */
|
||||
|
@ -326,24 +354,32 @@ goodChecksum(int partnum)
|
|||
uint16_t total = 0;
|
||||
for(int w = 0; w <= 0x3F; w++)
|
||||
total += word(w, partnum);
|
||||
|
||||
if (total == NVM_CHECKSUM)
|
||||
return 1;
|
||||
|
||||
fprintf(stderr, "WARNING: BAD checksum in part %d\n", partnum);
|
||||
return (errno = ECANCELED) & 0;
|
||||
errno = ECANCELED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* write the nvm parts back to the file */
|
||||
void
|
||||
writeGbe(void)
|
||||
{
|
||||
err_if((cmd == writeGbe) && !(goodChecksum(0) || goodChecksum(1)));
|
||||
if (cmd == writeGbe) /* cmd swap calls writeGbE; need valid checksum */
|
||||
err_if(!(goodChecksum(0) || goodChecksum(1)));
|
||||
|
||||
for (int p = 0, x = (cmd == writeGbe) ? 1 : 0; p < 2; p++) {
|
||||
if ((!nvmPartChanged[p]) && (cmd != writeGbe))
|
||||
continue;
|
||||
swap(p ^ x);
|
||||
|
||||
swap(p ^ x); /* swap bytes on big-endian host CPUs */
|
||||
|
||||
err_if(pwrite(fd, (uint8_t *) gbe[p ^ x], nf, p * partsize)
|
||||
== -1);
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
err_if(close(fd) == -1);
|
||||
}
|
||||
|
@ -354,6 +390,7 @@ swap(int partnum)
|
|||
{
|
||||
size_t w, x;
|
||||
uint8_t *n = (uint8_t *) gbe[partnum];
|
||||
|
||||
for (w = nf * ((uint8_t *) &e)[0], x = 1; w < nf; w += 2, x += 2)
|
||||
n[w] ^= n[x], n[x] ^= n[w], n[w] ^= n[x];
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue