diff options
Diffstat (limited to 'util/nvmutil/command.c')
| -rw-r--r-- | util/nvmutil/command.c | 603 |
1 files changed, 0 insertions, 603 deletions
diff --git a/util/nvmutil/command.c b/util/nvmutil/command.c deleted file mode 100644 index e04f3098..00000000 --- a/util/nvmutil/command.c +++ /dev/null @@ -1,603 +0,0 @@ -/* SPDX-License-Identifier: MIT - * - * Copyright (c) 2022-2026 Leah Rowe <leah@libreboot.org> - * - * Command handlers for nvmutil - */ - -#ifdef __OpenBSD__ -#include <sys/param.h> -#endif -#include <sys/types.h> -#include <sys/stat.h> - -#include <errno.h> -#include <fcntl.h> -#include <limits.h> -#include <stdarg.h> -#include <stddef.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> -#include <unistd.h> - -#include "include/common.h" - -/* - * Guard against regressions by maintainers (command table) - */ -void -sanitize_command_list(void) -{ - struct xstate *x = xstatus(); - - unsigned long c; - unsigned long num_commands; - - num_commands = items(x->cmd); - - for (c = 0; c < num_commands; c++) - sanitize_command_index(c); -} - -/* - * TODO: specific config checks per command - */ -void -sanitize_command_index(unsigned long c) -{ - struct xstate *x = xstatus(); - struct commands *cmd; - - int _flag; - unsigned long gbe_rw_size; - - cmd = &x->cmd[c]; - - check_command_num(c); - - if (cmd->argc < 3) - err(EINVAL, "cmd index %lu: argc below 3, %d", - (unsigned long)c, cmd->argc); - - if (cmd->str == NULL) - err(EINVAL, "cmd index %lu: NULL str", - (unsigned long)c); - - if (*cmd->str == '\0') - err(EINVAL, "cmd index %lu: empty str", - (unsigned long)c); - - if (xstrxlen(cmd->str, MAX_CMD_LEN + 1) > - MAX_CMD_LEN) { - err(EINVAL, "cmd index %lu: str too long: %s", - (unsigned long)c, cmd->str); - } - - if (cmd->run == NULL) - err(EINVAL, "cmd index %lu: cmd ptr null", - (unsigned long)c); - - check_bin(cmd->arg_part, "cmd.arg_part"); - check_bin(cmd->chksum_read, "cmd.chksum_read"); - check_bin(cmd->chksum_write, "cmd.chksum_write"); - - gbe_rw_size = cmd->rw_size; - - switch (gbe_rw_size) { - case GBE_PART_SIZE: - case NVM_SIZE: - break; - default: - err(EINVAL, "Unsupported rw_size: %lu", - (unsigned long)gbe_rw_size); - } - - if (gbe_rw_size > GBE_PART_SIZE) - err(EINVAL, "rw_size larger than GbE part: %lu", - (unsigned long)gbe_rw_size); - - _flag = (cmd->flags & O_ACCMODE); - - if (_flag != O_RDONLY && - _flag != O_RDWR) - err(EINVAL, "invalid cmd.flags setting"); -} - -void -set_cmd(int argc, char *argv[]) -{ - struct xstate *x = xstatus(); - const char *cmd; - - unsigned long c; - - for (c = 0; c < items(x->cmd); c++) { - - cmd = x->cmd[c].str; - - /* not the right command */ - if (xstrxcmp(argv[2], cmd, MAX_CMD_LEN) != 0) - continue; - - /* valid command found */ - if (argc >= x->cmd[c].argc) { - x->no_cmd = 0; - x->i = c; /* set command */ - - return; - } - - err(EINVAL, - "Too few args on command '%s'", cmd); - } - - x->no_cmd = 1; -} - -void -set_cmd_args(int argc, char *argv[]) -{ - struct xstate *x = xstatus(); - struct commands *cmd; - struct xfile *f; - unsigned long i; - - i = x->i; - cmd = &x->cmd[i]; - f = &x->f; - - if (!valid_command(i) || argc < 3) - usage(); - - if (x->no_cmd) - usage(); - - /* Maintainer bugs */ - if (cmd->arg_part && argc < 4) - err(EINVAL, - "arg_part set for command that needs argc4"); - - if (cmd->arg_part && i == CMD_SETMAC) - err(EINVAL, - "arg_part set on CMD_SETMAC"); - - if (i == CMD_SETMAC) { - - if (argc >= 4) - x->mac.str = argv[3]; - else - x->mac.str = x->mac.rmac; - - } else if (cmd->arg_part) { - - f->part = conv_argv_part_num(argv[3]); - } -} - -unsigned long -conv_argv_part_num(const char *part_str) -{ - unsigned char ch; - - if (part_str[0] == '\0' || part_str[1] != '\0') - err(EINVAL, "Partnum string '%s' wrong length", part_str); - - /* char signedness is implementation-defined */ - ch = (unsigned char)part_str[0]; - if (ch < '0' || ch > '1') - err(EINVAL, "Bad part number (%c)", ch); - - return (unsigned long)(ch - '0'); -} -void -run_cmd(void) -{ - struct xstate *x = xstatus(); - unsigned long i; - void (*run)(void); - - i = x->i; - run = x->cmd[i].run; - - check_command_num(i); - - if (run == NULL) - err(EINVAL, "Command %lu: null ptr", i); - - run(); - - for (i = 0; i < items(x->cmd); i++) - x->cmd[i].run = cmd_helper_err; -} - -void -check_command_num(unsigned long c) -{ - if (!valid_command(c)) - err(EINVAL, "Invalid run_cmd arg: %lu", - (unsigned long)c); -} - -unsigned char -valid_command(unsigned long c) -{ - struct xstate *x = xstatus(); - struct commands *cmd; - - if (c >= items(x->cmd)) - return 0; - - cmd = &x->cmd[c]; - - if (c != cmd->chk) - err(EINVAL, - "Invalid cmd chk value (%lu) vs arg: %lu", - cmd->chk, c); - - return 1; -} - -void -cmd_helper_setmac(void) -{ - struct xstate *x = xstatus(); - unsigned long partnum; - struct macaddr *mac; - - mac = &x->mac; - - check_cmd(cmd_helper_setmac, "setmac"); - - printf("MAC address to be written: %s\n", mac->str); - parse_mac_string(); - - for (partnum = 0; partnum < 2; partnum++) - write_mac_part(partnum); -} - -void -parse_mac_string(void) -{ - struct xstate *x = xstatus(); - struct macaddr *mac; - - unsigned long mac_byte; - - mac = &x->mac; - - if (xstrxlen(x->mac.str, 18) != 17) - err(EINVAL, "MAC address is the wrong length"); - - memset(mac->mac_buf, 0, sizeof(mac->mac_buf)); - - for (mac_byte = 0; mac_byte < 6; mac_byte++) - set_mac_byte(mac_byte); - - if ((mac->mac_buf[0] | mac->mac_buf[1] | mac->mac_buf[2]) == 0) - err(EINVAL, "Must not specify all-zeroes MAC address"); - - if (mac->mac_buf[0] & 1) - err(EINVAL, "Must not specify multicast MAC address"); -} - -void -set_mac_byte(unsigned long mac_byte_pos) -{ - struct xstate *x = xstatus(); - struct macaddr *mac; - - char separator; - - unsigned long mac_str_pos; - unsigned long mac_nib_pos; - - mac = &x->mac; - - mac_str_pos = mac_byte_pos * 3; - - if (mac_str_pos < 15) { - if ((separator = mac->str[mac_str_pos + 2]) != ':') - err(EINVAL, "Invalid MAC address separator '%c'", - separator); - } - - for (mac_nib_pos = 0; mac_nib_pos < 2; mac_nib_pos++) - set_mac_nib(mac_str_pos, mac_byte_pos, mac_nib_pos); -} - -void -set_mac_nib(unsigned long mac_str_pos, - unsigned long mac_byte_pos, unsigned long mac_nib_pos) -{ - struct xstate *x = xstatus(); - struct macaddr *mac; - - char mac_ch; - unsigned short hex_num; - - mac = &x->mac; - - mac_ch = mac->str[mac_str_pos + mac_nib_pos]; - - if ((hex_num = hextonum(mac_ch)) > 15) - err(EINVAL, "Invalid character '%c'", - mac->str[mac_str_pos + mac_nib_pos]); - - /* - * If random, ensure that local/unicast bits are set. - */ - if ((mac_byte_pos == 0) && (mac_nib_pos == 1) && - ((mac_ch | 0x20) == 'x' || - (mac_ch == '?'))) - hex_num = (hex_num & 0xE) | 2; /* local, unicast */ - - /* - * MAC words stored big endian in-file, little-endian - * logically, so we reverse the order. - */ - mac->mac_buf[mac_byte_pos >> 1] |= hex_num << - (((mac_byte_pos & 1) << 3) /* left or right byte? */ - | ((mac_nib_pos ^ 1) << 2)); /* left or right nib? */ -} - -void -write_mac_part(unsigned long partnum) -{ - struct xstate *x = xstatus(); - struct xfile *f; - struct macaddr *mac; - - unsigned long w; - - f = &x->f; - mac = &x->mac; - - check_bin(partnum, "part number"); - if (!f->part_valid[partnum]) - return; - - for (w = 0; w < 3; w++) - set_nvm_word(w, partnum, mac->mac_buf[w]); - - printf("Wrote MAC address to part %lu: ", - (unsigned long)partnum); - print_mac_from_nvm(partnum); -} - -void -cmd_helper_dump(void) -{ - struct xstate *x = xstatus(); - struct xfile *f; - - unsigned long p; - - f = &x->f; - - check_cmd(cmd_helper_dump, "dump"); - - f->part_valid[0] = good_checksum(0); - f->part_valid[1] = good_checksum(1); - - for (p = 0; p < 2; p++) { - - if (!f->part_valid[p]) { - - fprintf(stderr, - "BAD checksum %04x in part %lu (expected %04x)\n", - nvm_word(NVM_CHECKSUM_WORD, p), - (unsigned long)p, - calculated_checksum(p)); - } - - printf("MAC (part %lu): ", - (unsigned long)p); - - print_mac_from_nvm(p); - - hexdump(p); - } -} - -void -print_mac_from_nvm(unsigned long partnum) -{ - unsigned long c; - unsigned short val16; - - for (c = 0; c < 3; c++) { - val16 = nvm_word(c, partnum); - printf("%02x:%02x", - (unsigned int)(val16 & 0xff), - (unsigned int)(val16 >> 8)); - if (c == 2) - printf("\n"); - else - printf(":"); - } -} - -void -hexdump(unsigned long partnum) -{ - unsigned long c; - unsigned long row; - unsigned short val16; - - for (row = 0; row < 8; row++) { - - printf("%08lx ", - (unsigned long)((unsigned long)row << 4)); - - for (c = 0; c < 8; c++) { - - val16 = nvm_word((row << 3) + c, partnum); - - if (c == 4) - printf(" "); - - printf(" %02x %02x", - (unsigned int)(val16 & 0xff), - (unsigned int)(val16 >> 8)); - - } - - printf("\n"); - } -} - -void -cmd_helper_swap(void) -{ - struct xstate *x = xstatus(); - struct xfile *f; - - check_cmd(cmd_helper_swap, "swap"); - - f = &x->f; - - x_v_memcpy( - f->buf + (unsigned long)GBE_WORK_SIZE, - f->buf, - GBE_PART_SIZE); - - x_v_memcpy( - f->buf, - f->buf + (unsigned long)GBE_PART_SIZE, - GBE_PART_SIZE); - - x_v_memcpy( - f->buf + (unsigned long)GBE_PART_SIZE, - f->buf + (unsigned long)GBE_WORK_SIZE, - GBE_PART_SIZE); - - set_part_modified(0); - set_part_modified(1); -} - -void -cmd_helper_copy(void) -{ - struct xstate *x = xstatus(); - struct xfile *f; - - check_cmd(cmd_helper_copy, "copy"); - - f = &x->f; - - x_v_memcpy( - f->buf + (unsigned long)((f->part ^ 1) * GBE_PART_SIZE), - f->buf + (unsigned long)(f->part * GBE_PART_SIZE), - GBE_PART_SIZE); - - set_part_modified(f->part ^ 1); -} - -void -cmd_helper_cat(void) -{ - struct xstate *x = xstatus(); - check_cmd(cmd_helper_cat, "cat"); - - x->cat = 0; - cat(0); -} - -void -cmd_helper_cat16(void) -{ - struct xstate *x = xstatus(); - check_cmd(cmd_helper_cat16, "cat16"); - - x->cat = 1; - cat(1); -} - -void -cmd_helper_cat128(void) -{ - struct xstate *x = xstatus(); - check_cmd(cmd_helper_cat128, "cat128"); - - x->cat = 15; - cat(15); -} - -void -cat(unsigned long nff) -{ - struct xstate *x = xstatus(); - struct xfile *f; - - unsigned long p; - unsigned long ff; - - f = &x->f; - - p = 0; - ff = 0; - - if ((unsigned long)x->cat != nff) { - - err(ECANCELED, "erroneous call to cat"); - } - - fflush(NULL); - - memset(f->pad, 0xff, GBE_PART_SIZE); - - for (p = 0; p < 2; p++) { - - cat_buf(f->bufcmp + - (unsigned long)(p * (f->gbe_file_size >> 1))); - - for (ff = 0; ff < nff; ff++) { - - cat_buf(f->pad); - } - } -} - -void -cat_buf(unsigned char *b) -{ - if (b == NULL) - err(errno, "null pointer in cat command"); - - if (rw_file_exact(STDOUT_FILENO, b, - GBE_PART_SIZE, 0, IO_WRITE, LOOP_EAGAIN, LOOP_EINTR, - MAX_ZERO_RW_RETRY, OFF_ERR) < 0) - err(errno, "stdout: cat"); -} -void -check_cmd(void (*fn)(void), - const char *name) -{ - struct xstate *x = xstatus(); - unsigned long i; - - if (x->cmd[x->i].run != fn) - err(ECANCELED, "Running %s, but cmd %s is set", - name, x->cmd[x->i].str); - - /* - * In addition to making sure we ran - * the right command, we now disable - * all commands from running again - * - * the _nop function will just call - * err() immediately - */ - - for (i = 0; i < items(x->cmd); i++) - x->cmd[i].run = cmd_helper_err; -} - -void -cmd_helper_err(void) -{ - err(ECANCELED, - "Erroneously running command twice"); -} |
