From 0d98d738708c64c59dcc06553cb1abebf6606e4a Mon Sep 17 00:00:00 2001 From: Leah Rowe Date: Wed, 5 Apr 2023 23:55:04 +0100 Subject: 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) --- util/nvmutil/nvmutil.c | 141 ++++++++++++++++++++----------------------------- 1 file changed, 56 insertions(+), 85 deletions(-) (limited to 'util') diff --git a/util/nvmutil/nvmutil.c b/util/nvmutil/nvmutil.c index b57965c5..c86291c6 100644 --- a/util/nvmutil/nvmutil.c +++ b/util/nvmutil/nvmutil.c @@ -48,17 +48,19 @@ void cmd_copy(void); int validChecksum(int partnum); uint16_t word(int pos16, int partnum); 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); #define FILENAME argv[1] #define COMMAND argv[2] #define MAC_ADDRESS argv[3] #define PARTNUM argv[3] +#define SIZE_2KB 0x800 #define SIZE_4KB 0x1000 #define SIZE_8KB 0x2000 -uint8_t buf[SIZE_8KB]; +uint16_t buf16[SIZE_4KB]; +uint8_t *buf; size_t gbe[2]; uint8_t skipread[2] = {0, 0}; @@ -66,7 +68,7 @@ int part, gbeWriteAttempted = 0, gbeFileModified = 0; uint8_t nvmPartModified[2] = {0, 0}; uint16_t test; -uint8_t little_endian; +uint8_t big_endian; int main(int argc, char *argv[]) @@ -81,10 +83,11 @@ main(int argc, char *argv[]) err(errno, "pledge"); #endif + buf = (uint8_t *) &buf16; gbe[1] = (gbe[0] = (size_t) buf) + SIZE_4KB; test = 1; - little_endian = ((uint8_t *) &test)[0]; + big_endian = ((uint8_t *) &test)[0] ^ 1; if (argc == 3) { 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) err(errno, "%s", path); tr += r; + if (big_endian) + byteswap(nr, p); } 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 cmd_setmac(const char *strMac) { - int i, partnum; + uint8_t *b; uint16_t mac[3] = {0, 0, 0}; if (parseMacAddress(strMac, mac) == -1) 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)) continue; - for (i = 0; i < 3; i++) - setWord(i, partnum, mac[i]); + for (int w = 0; w < 3; w++) + setWord(w, partnum, mac[w]); part = partnum; cmd_setchecksum(); } @@ -202,53 +215,38 @@ cmd_setmac(const char *strMac) int parseMacAddress(const char *strMac, uint16_t *mac) { - int i, nib, byte; - uint8_t val8; - uint16_t val16; + int nib, byte; + uint8_t h; uint64_t total = 0; if (strnlen(strMac, 20) != 17) return -1; - for (i = 0; i < 16; i += 3) { + for (int i = 0; i < 16; i += 3) { if (i != 15) if (strMac[i + 2] != ':') return -1; byte = i / 3; - for (nib = 0; nib < 2; nib++, total += val8) { - if ((val8 = hextonum(strMac[i + nib])) > 15) + for (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] == '?') - val8 = (val8 & 0xE) | 2; - - val16 = val8; - if ((byte % 2) ^ 1) - val16 <<= 8; - val16 <<= 4 * (nib ^ 1); - mac[byte >> 1] |= val16; + h = (h & 0xE) | 2; + mac[byte >> 1] |= ((uint16_t ) h) + << ((8 * ((byte % 2) ^ 1)) + (4 * (nib ^ 1))); } } /* Disallow multicast and all-zero MAC addresses */ - test = mac[0]; - if (little_endian) - 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; + return ((total == 0) || (mac[0] & 0x100)) + ? -1 : 0; } uint8_t hextonum(char chs) { - uint8_t val8, ch; - ch = (uint8_t) chs; + uint8_t val8, ch = (uint8_t) chs; if ((ch >= '0') && (ch <= '9')) val8 = ch - '0'; @@ -288,9 +286,8 @@ rhex(void) void cmd_dump(void) { - int numInvalid, partnum; + int partnum, numInvalid = 0; - numInvalid = 0; for (partnum = 0; (partnum < 2); partnum++) { if (!validChecksum(partnum)) ++numInvalid; @@ -307,18 +304,11 @@ cmd_dump(void) void showmac(int partnum) { - int c; uint16_t val16; - uint8_t *byte; - for (c = 0; c < 3; c++) { + for (int c = 0; c < 3; c++) { val16 = word(c, partnum); - byte = (uint8_t *) &val16; - - if (!little_endian) - byteswap(byte); - - printf("%02x:%02x", byte[0], byte[1]); + printf("%02x:%02x", val16 & 0xff, val16 >> 8); if (c == 2) printf("\n"); else @@ -329,20 +319,13 @@ showmac(int partnum) void hexdump(int partnum) { - int row, c; uint16_t val16; - uint8_t *byte; - for (row = 0; row < 8; row++) { + for (int row = 0; row < 8; row++) { printf("%07x ", row << 4); - for (c = 0; c < 8; c++) { + for (int c = 0; c < 8; c++) { val16 = word((row << 3) + c, partnum); - byte = (uint8_t *) &val16; - - if (!little_endian) - byteswap(byte); - - printf("%02x%02x ", byte[1], byte[0]); + printf("%02x%02x ", val16 >> 8, val16 & 0xff); } printf("\n"); } @@ -351,10 +334,9 @@ hexdump(int partnum) void cmd_setchecksum(void) { - int c; - uint16_t val16; + uint16_t val16 = 0; - for (val16 = 0, c = 0; c < 0x3F; c++) + for (int c = 0; c < 0x3F; c++) val16 += word(c, part); setWord(0x3F, part, 0xBABA - val16); @@ -397,10 +379,9 @@ cmd_copy(void) int validChecksum(int partnum) { - int w; - uint16_t total; + uint16_t total = 0; - for(total = 0, w = 0; w <= 0x3F; w++) + for(int w = 0; w <= 0x3F; w++) total += word(w, partnum); if (total == 0xBABA) @@ -414,46 +395,34 @@ validChecksum(int partnum) uint16_t word(int pos16, int partnum) { - uint8_t *nbuf; - uint16_t pos8, val16; - - nbuf = (uint8_t *) gbe[partnum]; - pos8 = pos16 << 1; - val16 = nbuf[pos8 + 1]; - val16 <<= 8; - val16 |= nbuf[pos8]; - - return val16; + return buf16[pos16 + (partnum << 11)]; } void setWord(int pos16, int partnum, uint16_t val16) { - uint8_t val8[2], *nbuf; - uint16_t pos8; - gbeWriteAttempted = 1; if (word(pos16, partnum) == val16) return; - nbuf = (uint8_t *) gbe[partnum]; - val8[0] = (uint8_t) (val16 & 0xff); - val8[1] = (uint8_t) (val16 >> 8); - pos8 = pos16 << 1; - - nbuf[pos8] = val8[0]; - nbuf[pos8 + 1] = val8[1]; + buf16[pos16 + (partnum << 11)] = val16; gbeFileModified = 1; nvmPartModified[partnum] = 1; } void -byteswap(uint8_t *byte) +byteswap(int n, int partnum) { - byte[0] ^= byte[1]; - byte[1] ^= byte[0]; - byte[0] ^= byte[1]; + int b1, b2, wcount = n >> 1; + uint8_t *nbuf = (uint8_t *) gbe[partnum]; + + for (int w = 0; w < wcount; w++) { + b1 = b2 = w << 1; + nbuf[b1] ^= nbuf[++b2]; + nbuf[b2] ^= nbuf[b1]; + nbuf[b1] ^= nbuf[b2]; + } } void @@ -478,6 +447,8 @@ writeGbeFile(int *fd, const char *filename) "Part %d NOT modified\n", p); goto next_part; } + if (big_endian) + byteswap(nw, p); if (pwrite((*fd), (uint8_t *) gbe[p], nw, p << 12) != nw) err(errno, "%s", filename); tw += nw; -- cgit v1.2.1