util/nvmutil: serious re-factoring (speed boost!)
word/setWord no longer mitigates endianness. instead, all bytes are swapped after reading and before writing the file, and only if the host is big endian this improves performance on little endian hosts, which is most machines, and the code is much simpler, so it's more robust and less likely to break mac address endianness made more clear in code, including with a comment that explains it (the nvm section contains little endian words, *except* the mac address whose words are stored big endian)fsdg20230625
parent
b0fa54ac41
commit
0d98d73870
|
@ -48,17 +48,19 @@ void cmd_copy(void);
|
||||||
int validChecksum(int partnum);
|
int validChecksum(int partnum);
|
||||||
uint16_t word(int pos16, int partnum);
|
uint16_t word(int pos16, int partnum);
|
||||||
void setWord(int pos16, int partnum, uint16_t val16);
|
void setWord(int pos16, int partnum, uint16_t val16);
|
||||||
void byteswap(uint8_t *byte);
|
void byteswap(int n, int partnum);
|
||||||
void writeGbeFile(int *fd, const char *filename);
|
void writeGbeFile(int *fd, const char *filename);
|
||||||
|
|
||||||
#define FILENAME argv[1]
|
#define FILENAME argv[1]
|
||||||
#define COMMAND argv[2]
|
#define COMMAND argv[2]
|
||||||
#define MAC_ADDRESS argv[3]
|
#define MAC_ADDRESS argv[3]
|
||||||
#define PARTNUM argv[3]
|
#define PARTNUM argv[3]
|
||||||
|
#define SIZE_2KB 0x800
|
||||||
#define SIZE_4KB 0x1000
|
#define SIZE_4KB 0x1000
|
||||||
#define SIZE_8KB 0x2000
|
#define SIZE_8KB 0x2000
|
||||||
|
|
||||||
uint8_t buf[SIZE_8KB];
|
uint16_t buf16[SIZE_4KB];
|
||||||
|
uint8_t *buf;
|
||||||
size_t gbe[2];
|
size_t gbe[2];
|
||||||
uint8_t skipread[2] = {0, 0};
|
uint8_t skipread[2] = {0, 0};
|
||||||
|
|
||||||
|
@ -66,7 +68,7 @@ int part, gbeWriteAttempted = 0, gbeFileModified = 0;
|
||||||
uint8_t nvmPartModified[2] = {0, 0};
|
uint8_t nvmPartModified[2] = {0, 0};
|
||||||
|
|
||||||
uint16_t test;
|
uint16_t test;
|
||||||
uint8_t little_endian;
|
uint8_t big_endian;
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
|
@ -81,10 +83,11 @@ main(int argc, char *argv[])
|
||||||
err(errno, "pledge");
|
err(errno, "pledge");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
buf = (uint8_t *) &buf16;
|
||||||
gbe[1] = (gbe[0] = (size_t) buf) + SIZE_4KB;
|
gbe[1] = (gbe[0] = (size_t) buf) + SIZE_4KB;
|
||||||
|
|
||||||
test = 1;
|
test = 1;
|
||||||
little_endian = ((uint8_t *) &test)[0];
|
big_endian = ((uint8_t *) &test)[0] ^ 1;
|
||||||
|
|
||||||
if (argc == 3) {
|
if (argc == 3) {
|
||||||
if (strcmp(COMMAND, "dump") == 0) {
|
if (strcmp(COMMAND, "dump") == 0) {
|
||||||
|
@ -176,6 +179,8 @@ readGbeFile(int *fd, const char *path, int flags, size_t nr)
|
||||||
if ((r = pread((*fd), (uint8_t *) gbe[p], nr, p << 12)) == -1)
|
if ((r = pread((*fd), (uint8_t *) gbe[p], nr, p << 12)) == -1)
|
||||||
err(errno, "%s", path);
|
err(errno, "%s", path);
|
||||||
tr += r;
|
tr += r;
|
||||||
|
if (big_endian)
|
||||||
|
byteswap(nr, p);
|
||||||
}
|
}
|
||||||
printf("%d bytes read from file: `%s`\n", tr, path);
|
printf("%d bytes read from file: `%s`\n", tr, path);
|
||||||
}
|
}
|
||||||
|
@ -183,17 +188,25 @@ readGbeFile(int *fd, const char *path, int flags, size_t nr)
|
||||||
void
|
void
|
||||||
cmd_setmac(const char *strMac)
|
cmd_setmac(const char *strMac)
|
||||||
{
|
{
|
||||||
int i, partnum;
|
uint8_t *b;
|
||||||
uint16_t mac[3] = {0, 0, 0};
|
uint16_t mac[3] = {0, 0, 0};
|
||||||
|
|
||||||
if (parseMacAddress(strMac, mac) == -1)
|
if (parseMacAddress(strMac, mac) == -1)
|
||||||
err(errno = ECANCELED, "Bad MAC address");
|
err(errno = ECANCELED, "Bad MAC address");
|
||||||
|
|
||||||
for (partnum = 0; partnum < 2; partnum++) {
|
/* nvm words are little endian, *except* the mac address. swap bytes */
|
||||||
|
for (int w = 0; w < 3; w++) {
|
||||||
|
b = (uint8_t *) &mac[w];
|
||||||
|
b[0] ^= b[1];
|
||||||
|
b[1] ^= b[0];
|
||||||
|
b[0] ^= b[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int partnum = 0; partnum < 2; partnum++) {
|
||||||
if (!validChecksum(partnum))
|
if (!validChecksum(partnum))
|
||||||
continue;
|
continue;
|
||||||
for (i = 0; i < 3; i++)
|
for (int w = 0; w < 3; w++)
|
||||||
setWord(i, partnum, mac[i]);
|
setWord(w, partnum, mac[w]);
|
||||||
part = partnum;
|
part = partnum;
|
||||||
cmd_setchecksum();
|
cmd_setchecksum();
|
||||||
}
|
}
|
||||||
|
@ -202,53 +215,38 @@ cmd_setmac(const char *strMac)
|
||||||
int
|
int
|
||||||
parseMacAddress(const char *strMac, uint16_t *mac)
|
parseMacAddress(const char *strMac, uint16_t *mac)
|
||||||
{
|
{
|
||||||
int i, nib, byte;
|
int nib, byte;
|
||||||
uint8_t val8;
|
uint8_t h;
|
||||||
uint16_t val16;
|
|
||||||
uint64_t total = 0;
|
uint64_t total = 0;
|
||||||
|
|
||||||
if (strnlen(strMac, 20) != 17)
|
if (strnlen(strMac, 20) != 17)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
for (i = 0; i < 16; i += 3) {
|
for (int i = 0; i < 16; i += 3) {
|
||||||
if (i != 15)
|
if (i != 15)
|
||||||
if (strMac[i + 2] != ':')
|
if (strMac[i + 2] != ':')
|
||||||
return -1;
|
return -1;
|
||||||
byte = i / 3;
|
byte = i / 3;
|
||||||
for (nib = 0; nib < 2; nib++, total += val8) {
|
for (nib = 0; nib < 2; nib++, total += h) {
|
||||||
if ((val8 = hextonum(strMac[i + nib])) > 15)
|
if ((h = hextonum(strMac[i + nib])) > 15)
|
||||||
return -1;
|
return -1;
|
||||||
if ((byte == 0) && (nib == 1))
|
if ((byte == 0) && (nib == 1))
|
||||||
if (strMac[i + nib] == '?')
|
if (strMac[i + nib] == '?')
|
||||||
val8 = (val8 & 0xE) | 2;
|
h = (h & 0xE) | 2;
|
||||||
|
mac[byte >> 1] |= ((uint16_t ) h)
|
||||||
val16 = val8;
|
<< ((8 * ((byte % 2) ^ 1)) + (4 * (nib ^ 1)));
|
||||||
if ((byte % 2) ^ 1)
|
|
||||||
val16 <<= 8;
|
|
||||||
val16 <<= 4 * (nib ^ 1);
|
|
||||||
mac[byte >> 1] |= val16;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Disallow multicast and all-zero MAC addresses */
|
/* Disallow multicast and all-zero MAC addresses */
|
||||||
test = mac[0];
|
return ((total == 0) || (mac[0] & 0x100))
|
||||||
if (little_endian)
|
? -1 : 0;
|
||||||
byteswap((uint8_t *) &test);
|
|
||||||
if (total == 0 || (((uint8_t *) &test)[0] & 1))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (little_endian)
|
|
||||||
for (i = 0; i < 3; i++)
|
|
||||||
byteswap((uint8_t *) &mac[i]);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t
|
uint8_t
|
||||||
hextonum(char chs)
|
hextonum(char chs)
|
||||||
{
|
{
|
||||||
uint8_t val8, ch;
|
uint8_t val8, ch = (uint8_t) chs;
|
||||||
ch = (uint8_t) chs;
|
|
||||||
|
|
||||||
if ((ch >= '0') && (ch <= '9'))
|
if ((ch >= '0') && (ch <= '9'))
|
||||||
val8 = ch - '0';
|
val8 = ch - '0';
|
||||||
|
@ -288,9 +286,8 @@ rhex(void)
|
||||||
void
|
void
|
||||||
cmd_dump(void)
|
cmd_dump(void)
|
||||||
{
|
{
|
||||||
int numInvalid, partnum;
|
int partnum, numInvalid = 0;
|
||||||
|
|
||||||
numInvalid = 0;
|
|
||||||
for (partnum = 0; (partnum < 2); partnum++) {
|
for (partnum = 0; (partnum < 2); partnum++) {
|
||||||
if (!validChecksum(partnum))
|
if (!validChecksum(partnum))
|
||||||
++numInvalid;
|
++numInvalid;
|
||||||
|
@ -307,18 +304,11 @@ cmd_dump(void)
|
||||||
void
|
void
|
||||||
showmac(int partnum)
|
showmac(int partnum)
|
||||||
{
|
{
|
||||||
int c;
|
|
||||||
uint16_t val16;
|
uint16_t val16;
|
||||||
uint8_t *byte;
|
|
||||||
|
|
||||||
for (c = 0; c < 3; c++) {
|
for (int c = 0; c < 3; c++) {
|
||||||
val16 = word(c, partnum);
|
val16 = word(c, partnum);
|
||||||
byte = (uint8_t *) &val16;
|
printf("%02x:%02x", val16 & 0xff, val16 >> 8);
|
||||||
|
|
||||||
if (!little_endian)
|
|
||||||
byteswap(byte);
|
|
||||||
|
|
||||||
printf("%02x:%02x", byte[0], byte[1]);
|
|
||||||
if (c == 2)
|
if (c == 2)
|
||||||
printf("\n");
|
printf("\n");
|
||||||
else
|
else
|
||||||
|
@ -329,20 +319,13 @@ showmac(int partnum)
|
||||||
void
|
void
|
||||||
hexdump(int partnum)
|
hexdump(int partnum)
|
||||||
{
|
{
|
||||||
int row, c;
|
|
||||||
uint16_t val16;
|
uint16_t val16;
|
||||||
uint8_t *byte;
|
|
||||||
|
|
||||||
for (row = 0; row < 8; row++) {
|
for (int row = 0; row < 8; row++) {
|
||||||
printf("%07x ", row << 4);
|
printf("%07x ", row << 4);
|
||||||
for (c = 0; c < 8; c++) {
|
for (int c = 0; c < 8; c++) {
|
||||||
val16 = word((row << 3) + c, partnum);
|
val16 = word((row << 3) + c, partnum);
|
||||||
byte = (uint8_t *) &val16;
|
printf("%02x%02x ", val16 >> 8, val16 & 0xff);
|
||||||
|
|
||||||
if (!little_endian)
|
|
||||||
byteswap(byte);
|
|
||||||
|
|
||||||
printf("%02x%02x ", byte[1], byte[0]);
|
|
||||||
}
|
}
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
@ -351,10 +334,9 @@ hexdump(int partnum)
|
||||||
void
|
void
|
||||||
cmd_setchecksum(void)
|
cmd_setchecksum(void)
|
||||||
{
|
{
|
||||||
int c;
|
uint16_t val16 = 0;
|
||||||
uint16_t val16;
|
|
||||||
|
|
||||||
for (val16 = 0, c = 0; c < 0x3F; c++)
|
for (int c = 0; c < 0x3F; c++)
|
||||||
val16 += word(c, part);
|
val16 += word(c, part);
|
||||||
|
|
||||||
setWord(0x3F, part, 0xBABA - val16);
|
setWord(0x3F, part, 0xBABA - val16);
|
||||||
|
@ -397,10 +379,9 @@ cmd_copy(void)
|
||||||
int
|
int
|
||||||
validChecksum(int partnum)
|
validChecksum(int partnum)
|
||||||
{
|
{
|
||||||
int w;
|
uint16_t total = 0;
|
||||||
uint16_t total;
|
|
||||||
|
|
||||||
for(total = 0, w = 0; w <= 0x3F; w++)
|
for(int w = 0; w <= 0x3F; w++)
|
||||||
total += word(w, partnum);
|
total += word(w, partnum);
|
||||||
|
|
||||||
if (total == 0xBABA)
|
if (total == 0xBABA)
|
||||||
|
@ -414,46 +395,34 @@ validChecksum(int partnum)
|
||||||
uint16_t
|
uint16_t
|
||||||
word(int pos16, int partnum)
|
word(int pos16, int partnum)
|
||||||
{
|
{
|
||||||
uint8_t *nbuf;
|
return buf16[pos16 + (partnum << 11)];
|
||||||
uint16_t pos8, val16;
|
|
||||||
|
|
||||||
nbuf = (uint8_t *) gbe[partnum];
|
|
||||||
pos8 = pos16 << 1;
|
|
||||||
val16 = nbuf[pos8 + 1];
|
|
||||||
val16 <<= 8;
|
|
||||||
val16 |= nbuf[pos8];
|
|
||||||
|
|
||||||
return val16;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
setWord(int pos16, int partnum, uint16_t val16)
|
setWord(int pos16, int partnum, uint16_t val16)
|
||||||
{
|
{
|
||||||
uint8_t val8[2], *nbuf;
|
|
||||||
uint16_t pos8;
|
|
||||||
|
|
||||||
gbeWriteAttempted = 1;
|
gbeWriteAttempted = 1;
|
||||||
if (word(pos16, partnum) == val16)
|
if (word(pos16, partnum) == val16)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
nbuf = (uint8_t *) gbe[partnum];
|
buf16[pos16 + (partnum << 11)] = val16;
|
||||||
val8[0] = (uint8_t) (val16 & 0xff);
|
|
||||||
val8[1] = (uint8_t) (val16 >> 8);
|
|
||||||
pos8 = pos16 << 1;
|
|
||||||
|
|
||||||
nbuf[pos8] = val8[0];
|
|
||||||
nbuf[pos8 + 1] = val8[1];
|
|
||||||
|
|
||||||
gbeFileModified = 1;
|
gbeFileModified = 1;
|
||||||
nvmPartModified[partnum] = 1;
|
nvmPartModified[partnum] = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
byteswap(uint8_t *byte)
|
byteswap(int n, int partnum)
|
||||||
{
|
{
|
||||||
byte[0] ^= byte[1];
|
int b1, b2, wcount = n >> 1;
|
||||||
byte[1] ^= byte[0];
|
uint8_t *nbuf = (uint8_t *) gbe[partnum];
|
||||||
byte[0] ^= byte[1];
|
|
||||||
|
for (int w = 0; w < wcount; w++) {
|
||||||
|
b1 = b2 = w << 1;
|
||||||
|
nbuf[b1] ^= nbuf[++b2];
|
||||||
|
nbuf[b2] ^= nbuf[b1];
|
||||||
|
nbuf[b1] ^= nbuf[b2];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -478,6 +447,8 @@ writeGbeFile(int *fd, const char *filename)
|
||||||
"Part %d NOT modified\n", p);
|
"Part %d NOT modified\n", p);
|
||||||
goto next_part;
|
goto next_part;
|
||||||
}
|
}
|
||||||
|
if (big_endian)
|
||||||
|
byteswap(nw, p);
|
||||||
if (pwrite((*fd), (uint8_t *) gbe[p], nw, p << 12) != nw)
|
if (pwrite((*fd), (uint8_t *) gbe[p], nw, p << 12) != nw)
|
||||||
err(errno, "%s", filename);
|
err(errno, "%s", filename);
|
||||||
tw += nw;
|
tw += nw;
|
||||||
|
|
Loading…
Reference in New Issue