diff options
| author | Leah Rowe <leah@libreboot.org> | 2026-03-18 19:30:32 +0000 |
|---|---|---|
| committer | Leah Rowe <leah@libreboot.org> | 2026-03-19 04:25:43 +0000 |
| commit | 2ed8db3adc19dd922e31082634146e159f65af2e (patch) | |
| tree | dd242e1f7a178ee0c925cd080d61bac22fd681f5 /util/nvmutil/lib/state.c | |
| parent | 6ccd54635fdec85f44a9960b93c52fde89c07f41 (diff) | |
util/nvmutil: major cleanup
handle init in xstatus()
it's now a singleton design
also tidied up some other code
also removed todo.c. bloat.
will do all those anyway.
too much change. i just kept
touching the code until it
looked good
Signed-off-by: Leah Rowe <leah@libreboot.org>
Diffstat (limited to 'util/nvmutil/lib/state.c')
| -rw-r--r-- | util/nvmutil/lib/state.c | 192 |
1 files changed, 145 insertions, 47 deletions
diff --git a/util/nvmutil/lib/state.c b/util/nvmutil/lib/state.c index ec420594..f4f83e48 100644 --- a/util/nvmutil/lib/state.c +++ b/util/nvmutil/lib/state.c @@ -5,13 +5,6 @@ * This tool lets you modify Intel GbE NVM (Gigabit Ethernet * Non-Volatile Memory) images, e.g. change the MAC address. * These images configure your Intel Gigabit Ethernet adapter. - * - * This code is designed to be portable, running on as many - * Unix and Unix-like systems as possible (mainly BSD/Linux). - * - * Recommended CFLAGS for Clang/GCC: - * - * -Os -Wall -Wextra -Werror -pedantic -std=c90 */ #ifdef __OpenBSD__ @@ -34,40 +27,16 @@ #include "../include/common.h" /* - * Program state/command table - * Default config stored here, - * and copied to a newly allocated - * buffer in memory, then the pointer - * is passed. The rest of the program - * will manipulate this data. - */ -/* -TODO: -eventually, i will not have this return -a pointer at all. instead, a similar key -mechanism will be used for other access -functions e.g. word/set_word, err(needs -to clean up), and so on. then those -would return values if already initialised, -but would not permit additional init - will -decide exactly how to implement this at a -later state. - -this is part of an ongoing effort to introduce -extreme memory safety into this program. + * Initialise program state, + * load GbE file and verify + * data, ready for operation + * (singleton design) */ struct xstate * -xstatus(void) +xstatus(int argc, char *argv[]) { - static int first_run = 1; - static struct xstate us = { - /* .cmd (update cmd[] in the struct if adding to it) - DO NOT FORGET. or C will init zeroes/NULLs */ - - /* cmd[] members */ - /* DO NOT MESS THIS UP */ - /* items must be set *exactly* */ + /* DO NOT MESS THIS UP, OR THERE WILL BE DEMONS */ { { CMD_DUMP, "dump", cmd_helper_dump, ARGC_3, @@ -122,36 +91,165 @@ xstatus(void) /* .no_cmd (set 0 when a command is found) */ 1, - /* .xsize (size of the stuct will be stored here later) */ - 0, - /* .cat (cat helpers set this) */ -1 }; + static int first_run = 1; + if (!first_run) return &us; + us.f.buf = us.f.real_buf; + first_run = 0; + us.argv0 = argv[0]; + + if (argc > 1) + us.f.fname = argv[1]; + + if (argc < 3) + usage(); + +/* https://man.openbsd.org/pledge.2 + https://man.openbsd.org/unveil.2 */ +#if defined(__OpenBSD__) && defined(OpenBSD) +#if (OpenBSD) >= 604 + if (pledge("stdio flock rpath wpath cpath unveil", NULL) == -1) + err(errno, "pledge plus unveil"); +#elif (OpenBSD) >= 509 + if (pledge("stdio flock rpath wpath cpath", NULL) == -1) + err(errno, "pledge"); +#endif +#endif - us.xsize = sizeof(us); +#ifndef S_ISREG + err(ECANCELED, "Can't determine file types (S_ISREG undefined)"); +#endif - us.f.buf = us.f.real_buf; +#ifndef CHAR_BIT + err(ECANCELED, "Unknown char size"); +#else + if (CHAR_BIT != 8) + err(EINVAL, "Unsupported char size"); +#endif + +#if defined(__OpenBSD__) && defined(OpenBSD) && \ + (OpenBSD) >= 604 + /* can only use local tmp on openbsd, due to unveil */ + us.f.tname = new_tmpfile(&us.f.tmp_fd, 1, NULL); +#else + us.f.tname = new_tmpfile(&us.f.tmp_fd, 0, NULL); +#endif + if (us.f.tname == NULL) + err(errno, "Can't create tmpfile"); + if (*us.f.tname == '\0') + err(errno, "tmp dir is an empty string"); + +#if defined(__OpenBSD__) && defined(OpenBSD) && \ + OpenBSD >= 604 + if (unveil(f->tname, "rwc") == -1) + err(errno, "unveil rwc: %s", f->tname); +#endif + if (fstat(us.f.tmp_fd, &us.f.tmp_st) < 0) + err(errno, "%s: stat", us.f.tname); + + sanitize_command_list(); + + /* parse user command */ + set_cmd(argc, argv); + set_cmd_args(argc, argv); + +#if defined(__OpenBSD__) && defined(OpenBSD) && \ + (OpenBSD) >= 604 + if ((us.cmd[i].flags & O_ACCMODE) == O_RDONLY) { + if (unveil(us.f.fname, "r") == -1) + err(errno, "%s: unveil r", us.f.fname); + } else { + if (unveil(us.f.fname, "rwc") == -1) + err(errno, "%s: unveil rw", us.f.tname); + } + + if (unveil(us.f.tname, "rwc") == -1) + err(errno, "%s: unveil rwc", us.f.tname); + + if (unveil(NULL, NULL) == -1) + err(errno, "unveil block (rw)"); - us.f.gbe_fd = -1; - us.f.tmp_fd = -1; + if (pledge("stdio flock rpath wpath cpath", NULL) == -1) + err(errno, "pledge (kill unveil)"); +#endif + + open_gbe_file(); + + memset(us.f.real_buf, 0, sizeof(us.f.real_buf)); + memset(us.f.bufcmp, 0, sizeof(us.f.bufcmp)); + + /* for good measure */ + memset(us.f.pad, 0, sizeof(us.f.pad)); - us.f.tname = NULL; - us.f.fname = NULL; + copy_gbe(); + read_checksums(); return &us; } +void +err(int nvm_errval, const char *msg, ...) +{ + struct xstate *x = xstatus(0, NULL); + + va_list args; + + if (errno == 0) + errno = nvm_errval; + if (!errno) + errno = ECANCELED; + + (void)exit_cleanup(); + + if (x != NULL) + fprintf(stderr, "%s: ", getnvmprogname()); + + va_start(args, msg); + vfprintf(stderr, msg, args); + va_end(args); + + fprintf(stderr, ": %s\n", strerror(errno)); + + exit(EXIT_FAILURE); +} + +const char * +getnvmprogname(void) +{ + struct xstate *x = xstatus(0, NULL); + + const char *p; + static char fallback[] = "nvmutil"; + + char *rval = fallback; + + if (x != NULL) { + if (x->argv0 == NULL || *x->argv0 == '\0') + return ""; + + rval = x->argv0; + } + + p = x_c_strrchr(rval, '/'); + + if (p) + return p + 1; + else + return rval; +} + int exit_cleanup(void) { - struct xstate *x = xstatus(); + struct xstate *x = xstatus(0, NULL); struct xfile *f; int close_err; |
