summaryrefslogtreecommitdiff
path: root/util
diff options
context:
space:
mode:
authorLeah Rowe <leah@libreboot.org>2023-04-06 19:30:20 +0100
committerLeah Rowe <leah@libreboot.org>2023-04-06 19:30:20 +0100
commitd3ad50dcb48a104031f6cfdf022f787c3a58ec42 (patch)
tree9337c710636780e46427727fe8e7c135b14148e8 /util
parent7c403fcd9b9920e202773c04accc79701c45ffbc (diff)
util/nvmutil: add useful code comments
Diffstat (limited to 'util')
-rw-r--r--util/nvmutil/nvmutil.c55
1 files changed, 39 insertions, 16 deletions
diff --git a/util/nvmutil/nvmutil.c b/util/nvmutil/nvmutil.c
index cdfcbc32..b77b28ad 100644
--- a/util/nvmutil/nvmutil.c
+++ b/util/nvmutil/nvmutil.c
@@ -21,6 +21,11 @@
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
+/*
+ * This file is part of the Libreboot project. Documentation available here:
+ * https://libreboot.org/docs/install/nvmutil.html
+ */
+
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
@@ -78,33 +83,33 @@ main(int argc, char *argv[])
const char *strMac = NULL, *strRMac = "??:??:??:??:??:??";
#ifdef HAVE_PLEDGE
- if (pledge("stdio wpath", NULL) == -1)
- err(errno, "pledge");
+ if (pledge("stdio wpath", NULL) == -1) /* only used on openbsd */
+ err(errno, "pledge"); /* https://man.openbsd.org/pledge.2 */
#endif
buf = (uint8_t *) &buf16;
gbe[1] = (gbe[0] = (size_t) buf) + SIZE_4KB;
test = 1;
- big_endian = ((uint8_t *) &test)[0] ^ 1;
+ big_endian = ((uint8_t *) &test)[0] ^ 1; /* check host endianness */
if (argc == 3) {
if (strcmp(COMMAND, "dump") == 0) {
#ifdef HAVE_PLEDGE
if (pledge("stdio rpath", NULL) == -1)
- err(errno, "pledge");
+ err(errno, "pledge"); /* not very puffy */
#endif
flags = O_RDONLY;
cmd = &cmd_dump;
} else if (strcmp(COMMAND, "setmac") == 0)
- strMac = (char *) strRMac;
+ strMac = (char *) strRMac; /* random mac address */
else if (strcmp(COMMAND, "swap") == 0)
cmd = &cmd_swap;
} else if (argc == 4) {
if (strcmp(COMMAND, "setmac") == 0)
- strMac = MAC_ADDRESS;
+ strMac = MAC_ADDRESS; /* user-supplied mac address */
else if ((!((part = PARTNUM[0] - '0') == 0 || part == 1))
- || PARTNUM[1])
+ || PARTNUM[1]) /* only allow '1' or '0' */
errno = EINVAL;
else if (strcmp(COMMAND, "setchecksum") == 0)
cmd = &cmd_setchecksum;
@@ -129,6 +134,7 @@ main(int argc, char *argv[])
readGbeFile(&fd, FILENAME, flags, nr);
+ /* perform operation specified by the user */
if (strMac != NULL)
cmd_setmac(strMac);
else if (cmd != NULL)
@@ -145,6 +151,7 @@ nvmutil_exit:
return errno;
}
+/* load the gbe file into memory */
void
readGbeFile(int *fd, const char *path, int flags, size_t nr)
{
@@ -174,6 +181,7 @@ readGbeFile(int *fd, const char *path, int flags, size_t nr)
}
}
+/* set mac address on valid nvm parts, per user input */
void
cmd_setmac(const char *strMac)
{
@@ -193,12 +201,13 @@ cmd_setmac(const char *strMac)
if (!validChecksum(partnum))
continue;
for (int w = 0; w < 3; w++)
- setWord(w, partnum, mac[w]);
+ setWord(w, partnum, mac[w]); /* do not use memcpy! */
part = partnum;
cmd_setchecksum();
}
}
+/* read mac address from user input */
int
parseMacAddress(const char *strMac, uint16_t *mac)
{
@@ -239,11 +248,12 @@ hextonum(char ch)
else if ((ch >= 'a') && (ch <= 'f'))
return ch - 'a' + 10;
else if (ch == '?')
- return rhex();
+ return rhex(); /* random number */
else
return 16;
}
+/* generate a random number from 0 to 15, the unix way */
uint8_t
rhex(void)
{
@@ -261,6 +271,7 @@ rhex(void)
return rval;
}
+/* show mac address and hexdump of each nvm part */
void
cmd_dump(void)
{
@@ -276,6 +287,7 @@ cmd_dump(void)
errno = 0;
}
+/* show formatted mac address contained within the nvm part */
void
showmac(int partnum)
{
@@ -290,6 +302,7 @@ showmac(int partnum)
}
}
+/* output a hexdump of both nvm parts, bytes reversed to big-endian order */
void
hexdump(int partnum)
{
@@ -304,6 +317,7 @@ hexdump(int partnum)
}
}
+/* set a valid checksum on a given part */
void
cmd_setchecksum(void)
{
@@ -313,6 +327,7 @@ cmd_setchecksum(void)
setWord(0x3F, part, 0xBABA - val16);
}
+/* set invalid checksum, intentionally */
void
cmd_brick(void)
{
@@ -320,26 +335,28 @@ cmd_brick(void)
setWord(0x3F, part, (word(0x3F, part)) ^ 0xFF);
}
+/* swap the words of each part with each other */
void
cmd_swap(void)
{
if (validChecksum(1) || validChecksum(0)) {
- gbe[0] ^= gbe[1];
+ gbe[0] ^= gbe[1]; /* speed hack: xorswap pointers, not words */
gbe[1] ^= gbe[0];
gbe[0] ^= gbe[1];
- gbeFileModified = 1;
+ gbeFileModified = 1; /* not using setWord, so must set these */
nvmPartModified[0] = 1;
nvmPartModified[1] = 1;
errno = 0;
}
}
+/* overwrite one part with the other */
void
cmd_copy(void)
{
if (validChecksum(part)) {
- gbe[part ^ 1] = gbe[part];
- gbeFileModified = 1;
+ gbe[part ^ 1] = gbe[part]; /* pointer-based speed hack */
+ gbeFileModified = 1; /* not using setWord, so must set these */
nvmPartModified[part ^ 1] = 1;
}
}
@@ -358,12 +375,14 @@ validChecksum(int partnum)
return 0;
}
+/* fetch a word from gbe buffer */
uint16_t
word(int pos16, int partnum)
{
return buf16[pos16 + (partnum << 11)];
}
+/* write a word to gbe buffer, and record that a write has occured */
void
setWord(int pos16, int partnum, uint16_t val16)
{
@@ -375,6 +394,7 @@ setWord(int pos16, int partnum, uint16_t val16)
nvmPartModified[partnum] = 1;
}
+/* big-endian host compatibility: called post-read and again pre-write */
void
byteswap(int n, int partnum)
{
@@ -382,24 +402,27 @@ byteswap(int n, int partnum)
uint8_t *nbuf = (uint8_t *) gbe[partnum];
for (int w = 0; w < wcount; w++) {
b1 = b2 = w << 1;
+
+ /* xor-based swap method */
nbuf[b1] ^= nbuf[++b2];
nbuf[b2] ^= nbuf[b1];
nbuf[b1] ^= nbuf[b2];
}
}
+/* called after all operations are done, if gbe was modified */
void
writeGbeFile(int *fd, const char *filename)
{
int p, nw;
errno = 0;
if ((gbe[0] != gbe[1]) && (gbe[0] < gbe[1]))
- nw = 128; /* copy/swap command, so only write the nvm part */
+ nw = 128; /* write only the nvm part */
else
- nw = SIZE_4KB;
+ nw = SIZE_4KB; /* copy/swap, so only write everything */
for (p = 0; p < 2; p++) {
- if (gbe[0] > gbe[1])
+ if (gbe[0] > gbe[1]) /* write sequentially on-disk */
p ^= 1;
if (!nvmPartModified[p])
goto next_part;