diff options
author | Patrick Georgi <patrick.georgi@secunet.com> | 2011-01-28 07:47:10 +0000 |
---|---|---|
committer | Patrick Georgi <patrick.georgi@coresystems.de> | 2011-01-28 07:47:10 +0000 |
commit | c6d2b09f7673a33e75a4f5a38368e9684c2ecc79 (patch) | |
tree | a32b461e4b199f4f2506eab1f452a6ac9000e7c0 /util/nvramtool/cli | |
parent | c7ca3e5ca4f5e2e1c005f24905f6e0b466535525 (diff) | |
download | coreboot-c6d2b09f7673a33e75a4f5a38368e9684c2ecc79.tar.xz |
Move CLI portion of nvramtool into cli/ subdirectory as first step towards librarization.
Also: update one regex wrapper user.
Signed-off-by: Patrick Georgi <patrick.georgi@secunet.com>
Acked-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@6310 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
Diffstat (limited to 'util/nvramtool/cli')
-rw-r--r-- | util/nvramtool/cli/nvramtool.8 | 254 | ||||
-rw-r--r-- | util/nvramtool/cli/nvramtool.c | 863 | ||||
-rw-r--r-- | util/nvramtool/cli/opts.c | 259 | ||||
-rw-r--r-- | util/nvramtool/cli/opts.h | 79 |
4 files changed, 1455 insertions, 0 deletions
diff --git a/util/nvramtool/cli/nvramtool.8 b/util/nvramtool/cli/nvramtool.8 new file mode 100644 index 0000000000..9159a2a6dd --- /dev/null +++ b/util/nvramtool/cli/nvramtool.8 @@ -0,0 +1,254 @@ +.\"***************************************************************************\ +.\" nvramtool.8 +.\"*************************************************************************** +.\" Copyright (C) 2002, 2003 The Regents of the University of California. +.\" Produced at the Lawrence Livermore National Laboratory. +.\" Written by David S. Peterson <dsp@llnl.gov> <dave_peterson@pobox.com>. +.\" UCRL-CODE-2003-012 +.\" All rights reserved. +.\" +.\" This file is part of nvramtool, a utility for reading/writing coreboot +.\" parameters and displaying information from the coreboot table. +.\" For details, see http://coreboot.org/nvramtool. +.\" +.\" Please also read the file DISCLAIMER which is included in this software +.\" distribution. +.\" +.\" This program is free software; you can redistribute it and/or modify it +.\" under the terms of the GNU General Public License (as published by the +.\" Free Software Foundation) version 2, dated June 1991. +.\" +.\" This program is distributed in the hope that it will be useful, but +.\" WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY OF +.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the terms and +.\" conditions of the GNU General Public License for more details. +.\" +.\" You should have received a copy of the GNU General Public License along +.\" with this program; if not, write to the Free Software Foundation, Inc., +.\" 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +.\"***************************************************************************/ +.TH NVRAMTOOL 8 "September 2008" +.SH NAME +nvramtool \- read/write coreboot-related information +.SH SYNOPSIS +.B "nvramtool [OPTS] [-n] -r NAME" +.br +.B "nvramtool [OPTS] -e NAME" +.br +.B "nvramtool [OPTS] -a" +.br +.B "nvramtool [OPTS] -w NAME=VALUE" +.br +.B "nvramtool [OPTS] -p INPUT_FILE" +.br +.B "nvramtool [OPTS] -i" +.br +.B "nvramtool [OPTS] -c [VALUE]" +.br +.B "nvramtool [OPTS] -l [ARG]" +.br +.B "nvramtool [OPTS] -d" +.br +.B "nvramtool [OPTS] -Y" +.br +.B "nvramtool [OPTS] -b OUTPUT_FILE" +.br +.B "nvramtool [OPTS] -B INPUT_FILE" +.br +.B "nvramtool [OPTS] -x" +.br +.B "nvramtool [OPTS] -X DUMPFILE" +.br +.B "nvramtool [OPTS] -v" +.br +.B "nvramtool [OPTS] -h" +.SH DESCRIPTION +.B "nvramtool" +is a utility for reading/writing coreboot parameters and displaying +information from the coreboot table. + +The coreboot table resides in low physical memory. It is created at boot +time by coreboot, and contains various system information such as the type +of mainboard in use. It specifies locations in the CMOS (nonvolatile RAM) +where the coreboot parameters are stored. + +This program is intended for (x86-based) systems that use coreboot. For +information about coreboot, see +.br +http://www.coreboot.org/. +.SH PARAMETERS +.TP +.B "[-n] -r NAME" +Show the value of the coreboot parameter given by +.B "NAME." +If +.B "-n" +is specified, show only the value. Otherwise show both parameter name and +value. +.TP +.B "-e NAME" +Show all possible values for parameter given by +.B "NAME." +.TP +.B "-a" +Show the names and values for all coreboot parameters. +.TP +.B "-w NAME=VALUE" +Assign +.B "VALUE" +to coreboot parameter given by +.B "NAME." +.TP +.B "-p INPUT_FILE" +Assign values to coreboot parameters according to the contents of +.B "INPUT_FILE." +The format of this file is described below. +.TP +.B "-i" +This is similar to the +.B "-p" +option, except that the contents of the input file are taken from standard +input. +.TP +.B "-c [VALUE]" +If +.B "VALUE" +is present then set the CMOS checksum for the coreboot parameters to +.B "VALUE." +Otherwise, show the checksum value. +.TP +.B "-l [ARG]" +If +.B "ARG" +is present then show information from the coreboot table as specified by +.B "ARG." +Otherwise show all possible values for +.B "ARG." +.TP +.B "-d" +Do a low-level dump of the coreboot table. +.TP +.B "-Y" +Write CMOS layout information to standard output. If redirected to a file, +the layout information may be used as input for the +.B "'-y LAYOUT_FILE'" +option (see below). +.TP +.B "-b OUTPUT_FILE" +Write the contents of CMOS memory to the binary file +.B "OUTPUT_FILE." +The first 14 bytes of +.B "OUTPUT_FILE" +do not contain actual CMOS data, and are always written as zeros. This is +because the first 14 bytes of the CMOS area do not contain CMOS memory. These +bytes are involved with the functioning of the real time clock. +.TP +.B "-B INPUT_FILE" +Read binary data from +.B "INPUT_FILE" +and write the data to CMOS memory. The first 14 bytes of +.B "INPUT_FILE" +are skipped and data is written to CMOS starting at the 15th byte of the CMOS +area. This is because the first 14 bytes of the CMOS area do not contain CMOS +memory. These bytes are involved with the functioning of the real time clock. +.TP +.B "-x" +Show a hex dump of all CMOS data. The first 14 bytes of the dump do not +contain actual CMOS data, and are always shown as zeros. This is because the +first 14 bytes of the CMOS area do not contain CMOS memory. These bytes are +involved with the functioning of the real time clock. +.TP +.B "-X DUMPFILE" +Read binary data from +.B "DUMPFILE" +(presumably a CMOS dumpfile created using the +.B "-b OUTPUT_FILE" +option) and show a hex dump of the data. +.TP +.B "-v" +Show version information for this program. +.TP +.B "-h" +Show a help message for this program. +.SH "OPTIONS" +In all cases above, +.B "[OPTS]" +evaluates to the following: + +.B " [-y LAYOUT_FILE | -t]" + +The +.B "'-y LAYOUT_FILE'" +option tells nvramtool to obtain CMOS layout information from the contents of +.B "LAYOUT_FILE." +Likewise, the +.B "'-t'" +option tells nvramtool to obtain CMOS layout information from the CMOS option +table (contained within the coreboot table). If neither option is +specified, the CMOS option table is used by default. +.B "LAYOUT_FILE" +follows the format of the +.B "cmos.layout" +files provided by coreboot. + +If the coreboot installed on your system was built without specifying +.B "CONFIG_HAVE_OPTION_TABLE," +then the coreboot table will not contain a CMOS option table. In this case, +the +.B "'-y LAYOUT_FILE'" +option must be used. + +These two options are silently ignored when used in combination with other +options (such as +.B "-h," +for instance) for which they are not applicable. +.SH FILE FORMAT +For the +.B "-p" +option, +.B "INPUT_FILE" +must consist of a sequence of lines such that each line is either a blank +line, a comment, or an assignment. A blank line consists only of zero or +more whitespace characters (spaces and tabs). A comment is constructed as +follows: + +.B " [ws]#[text]" + +Here, +.B "[ws]" +indicates optional whitespace characters and +.B "[text]" +indicates optional text. Blank lines and comments are both ignored. An +assignment is constructed as follows: + +.B " [ws]NAME[ws]=[ws]VALUE[ws]" + +Here, +.B "NAME" +is the name of a coreboot parameter and +.B "VALUE" +is the value that will be assigned to +.B "NAME." +.B "VALUE" +is allowed to contain whitespace characters, but it must begin and end with +nonwhitespace characters. Note that each comment must appear on a line by +itself. If you attempt to add a comment to the end of an assignment, then the +comment will be interpreted as part of +.B "VALUE." +It is useful to observe that the output produced by both the +.B "-a" +and the +.B "'[-n] NAME'" +options (without +.B "-n" +specified) adheres to this file format. +.SH BUGS +This program does not implement any type of synchronization to ensure that +different processes don't stomp on each other when trying to access the +nonvolatile RAM simultaneously. Therefore, corruption of the BIOS parameter +values may occur if multiple instances of this program are executed +concurrently. +.SH AUTHORS +David S. Peterson <dsp@llnl.gov> <dave_peterson@pobox.com> +.br +Stefan Reinauer <stepan@coresystems.de> diff --git a/util/nvramtool/cli/nvramtool.c b/util/nvramtool/cli/nvramtool.c new file mode 100644 index 0000000000..e3e7e8875a --- /dev/null +++ b/util/nvramtool/cli/nvramtool.c @@ -0,0 +1,863 @@ +/*****************************************************************************\ + * nvramtool.c + ***************************************************************************** + * Copyright (C) 2002-2005 The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * Written by Dave Peterson <dsp@llnl.gov> <dave_peterson@pobox.com>. + * UCRL-CODE-2003-012 + * All rights reserved. + * + * This file is part of nvramtool, a utility for reading/writing coreboot + * parameters and displaying information from the coreboot table. + * For details, see http://coreboot.org/nvramtool. + * + * Please also read the file DISCLAIMER which is included in this software + * distribution. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License (as published by the + * Free Software Foundation) version 2, dated June 1991. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY OF + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the terms and + * conditions of the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +\*****************************************************************************/ + +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/mman.h> +#include "common.h" +#include "opts.h" +#include "lbtable.h" +#include "layout.h" +#include "layout_file.h" +#include "input_file.h" +#include "cmos_ops.h" +#include "cmos_lowlevel.h" +#include "reg_expr.h" +#include "hexdump.h" +#include "cbfs.h" + +typedef void (*op_fn_t) (void); + +static void op_show_version(void); +static void op_show_usage(void); +static void op_lbtable_show_info(void); +static void op_lbtable_dump(void); +static void op_show_param_values(void); +static void op_cmos_show_one_param(void); +static void op_cmos_show_all_params(void); +static void op_cmos_set_one_param(void); +static void op_cmos_set_params_stdin(void); +static void op_cmos_set_params_file(void); +static void op_cmos_checksum(void); +static void op_show_layout(void); +static void op_write_cmos_dump(void); +static void op_read_cmos_dump(void); +static void op_show_cmos_hex_dump(void); +static void op_show_cmos_dumpfile(void); +static int list_one_param(const char name[], int show_name); +static int list_all_params(void); +static void list_param_enums(const char name[]); +static void set_one_param(const char name[], const char value[]); +static void set_params(FILE * f); +static void parse_assignment(char arg[], const char **name, const char **value); +static int list_cmos_entry(const cmos_entry_t * e, int show_name); +static uint16_t convert_checksum_value(const char value[]); + +static const op_fn_t op_fns[] = { op_show_version, + op_show_usage, + op_lbtable_show_info, + op_lbtable_dump, + op_show_param_values, + op_cmos_show_one_param, + op_cmos_show_all_params, + op_cmos_set_one_param, + op_cmos_set_params_stdin, + op_cmos_set_params_file, + op_cmos_checksum, + op_show_layout, + op_write_cmos_dump, + op_read_cmos_dump, + op_show_cmos_hex_dump, + op_show_cmos_dumpfile +}; + +static const hexdump_format_t cmos_dump_format = + { 16, 2, "", " | ", " ", " | ", '.' }; + +/**************************************************************************** + * main + ****************************************************************************/ +int main(int argc, char *argv[]) +{ + void *cmos_default = NULL; + cmos_layout_get_fn_t fn = get_layout_from_cmos_table; + + parse_nvramtool_args(argc, argv); + + if (nvramtool_op_modifiers[NVRAMTOOL_MOD_USE_CMOS_LAYOUT_FILE].found) { + set_layout_filename(nvramtool_op_modifiers + [NVRAMTOOL_MOD_USE_CMOS_LAYOUT_FILE].param); + fn = get_layout_from_file; + } else if (nvramtool_op_modifiers[NVRAMTOOL_MOD_USE_CMOS_OPT_TABLE].found) { + fn = get_layout_from_cmos_table; + } else if (nvramtool_op_modifiers[NVRAMTOOL_MOD_USE_CBFS_FILE].found) { + open_cbfs(nvramtool_op_modifiers[NVRAMTOOL_MOD_USE_CBFS_FILE].param); + if (!nvramtool_op_modifiers[NVRAMTOOL_MOD_USE_CMOS_FILE].found) { + cmos_default = cbfs_find_file("cmos.default", CBFS_COMPONENT_CMOS_DEFAULT, NULL); + if (cmos_default == NULL) { + fprintf(stderr, "Need a cmos.default in the CBFS image or separate cmos file (-D).\n"); + exit(1); + } + } + } + if (nvramtool_op_modifiers[NVRAMTOOL_MOD_USE_CMOS_FILE].found) { + int fd; + struct stat fd_stat; + if ((fd = open(nvramtool_op_modifiers[NVRAMTOOL_MOD_USE_CMOS_FILE].param, O_RDWR | O_CREAT, 0666)) < 0) { + fprintf(stderr, "Couldn't open '%s'\n", nvramtool_op_modifiers[NVRAMTOOL_MOD_USE_CMOS_FILE].param); + exit(1); + } + if (fstat(fd, &fd_stat) == -1) { + fprintf(stderr, "Couldn't stat '%s'\n", nvramtool_op_modifiers[NVRAMTOOL_MOD_USE_CMOS_FILE].param); + exit(1); + } + if (fd_stat.st_size < 128) { + lseek(fd, 127, SEEK_SET); + write(fd, "\0", 1); + fsync(fd); + } + cmos_default = mmap(NULL, 128, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (cmos_default == MAP_FAILED) { + fprintf(stderr, "Couldn't map '%s'\n", nvramtool_op_modifiers[NVRAMTOOL_MOD_USE_CMOS_FILE].param); + exit(1); + } + } + if (cmos_default) { + select_hal(HAL_MEMORY, cmos_default); + fn = get_layout_from_cbfs_file; + } + + register_cmos_layout_get_fn(fn); + op_fns[nvramtool_op.op] (); + return 0; +} + +/**************************************************************************** + * op_show_version + * + * -v + * + * Show version information for this program. + ****************************************************************************/ +static void op_show_version(void) +{ + printf("This is %s version %s.\n", prog_name, prog_version); +} + +/**************************************************************************** + * op_show_usage + * + * -h + * + * Show a usage message for this program. + ****************************************************************************/ +static void op_show_usage(void) +{ + usage(stdout); +} + +/**************************************************************************** + * op_lbtable_show_info + * + * -l [ARG] + * + * If ARG is present, show coreboot table information specified by ARG. + * Else show all possible values for ARG. + ****************************************************************************/ +static void op_lbtable_show_info(void) +{ + if (nvramtool_op.param == NULL) + list_lbtable_choices(); + else { + get_lbtable(); + list_lbtable_item(nvramtool_op.param); + } +} + +/**************************************************************************** + * op_lbtable_dump + * + * -d + * + * Do low-level dump of coreboot table. + ****************************************************************************/ +static void op_lbtable_dump(void) +{ + get_lbtable(); + dump_lbtable(); +} + +/**************************************************************************** + * op_show_param_values + * + * -e NAME option + * + * Show all possible values for parameter NAME. + ****************************************************************************/ +static void op_show_param_values(void) +{ + get_cmos_layout(); + list_param_enums(nvramtool_op.param); +} + +/**************************************************************************** + * op_cmos_show_one_param + * + * [-n] -r NAME + * + * Show parameter NAME. If -n is specified, show value only. Else show name + * and value. + ****************************************************************************/ +static void op_cmos_show_one_param(void) +{ + int result; + + get_cmos_layout(); + result = list_one_param(nvramtool_op.param, + !nvramtool_op_modifiers + [NVRAMTOOL_MOD_SHOW_VALUE_ONLY].found); + cmos_checksum_verify(); + + if (result) + exit(1); +} + +/**************************************************************************** + * op_cmos_show_all_params + * + * -a + * + * Show names and values for all parameters. + ****************************************************************************/ +static void op_cmos_show_all_params(void) +{ + int result; + + get_cmos_layout(); + result = list_all_params(); + cmos_checksum_verify(); + + if (result) + exit(1); +} + +/**************************************************************************** + * op_cmos_set_one_param + * + * -w NAME=VALUE + * + * Set parameter NAME to VALUE. + ****************************************************************************/ +static void op_cmos_set_one_param(void) +{ + const char *name, *value; + + get_cmos_layout(); + + /* Separate 'NAME=VALUE' syntax into two strings representing NAME and + * VALUE. + */ + parse_assignment(nvramtool_op.param, &name, &value); + + set_one_param(name, value); +} + +/**************************************************************************** + * op_cmos_set_params_stdin + * + * -i + * + * Set parameters according to standard input. + ****************************************************************************/ +static void op_cmos_set_params_stdin(void) +{ + get_cmos_layout(); + set_params(stdin); +} + +/**************************************************************************** + * op_cmos_set_params_file + * + * -p INPUT_FILE + * + * Set parameters according to INPUT_FILE. + ****************************************************************************/ +static void op_cmos_set_params_file(void) +{ + FILE *f; + + if ((f = fopen(nvramtool_op.param, "r")) == NULL) { + fprintf(stderr, "%s: Can not open file %s for reading: %s\n", + prog_name, nvramtool_op.param, strerror(errno)); + exit(1); + } + + get_cmos_layout(); + set_params(f); + fclose(f); +} + +/**************************************************************************** + * op_cmos_checksum + * + * -c [VALUE] + * + * If VALUE is present, set coreboot CMOS checksum to VALUE. Else show + * checksum value. + ****************************************************************************/ +static void op_cmos_checksum(void) +{ + uint16_t checksum; + + get_cmos_layout(); + + if (nvramtool_op.param == NULL) { + set_iopl(3); + checksum = cmos_checksum_read(); + set_iopl(0); + printf("0x%x\n", checksum); + } else { + checksum = convert_checksum_value(nvramtool_op.param); + set_iopl(3); + cmos_checksum_write(checksum); + set_iopl(0); + } +} + +/**************************************************************************** + * op_show_layout + * + * -Y + * + * Write CMOS layout information to standard output. + ****************************************************************************/ +static void op_show_layout(void) +{ + get_cmos_layout(); + write_cmos_layout(stdout); +} + +/**************************************************************************** + * op_write_cmos_dump + * + * -b OUTPUT_FILE + * + * Write the contents of CMOS memory to a binary file. + ****************************************************************************/ +static void op_write_cmos_dump(void) +{ + unsigned char data[CMOS_SIZE]; + FILE *f; + + if ((f = fopen(nvramtool_op.param, "w")) == NULL) { + fprintf(stderr, "%s: Can not open file %s for writing: %s\n", + prog_name, nvramtool_op.param, strerror(errno)); + exit(1); + } + + set_iopl(3); + cmos_read_all(data); + set_iopl(0); + + if (fwrite(data, 1, CMOS_SIZE, f) != CMOS_SIZE) { + fprintf(stderr, "%s: Error writing CMOS data to file %s: %s\n", + prog_name, nvramtool_op.param, strerror(errno)); + exit(1); + } + + fclose(f); +} + +/**************************************************************************** + * op_read_cmos_dump + * + * -B INPUT_FILE + * + * Read binary data from a file and write the data to CMOS memory. + ****************************************************************************/ +static void op_read_cmos_dump(void) +{ + unsigned char data[CMOS_SIZE]; + size_t nr_bytes; + FILE *f; + + if ((f = fopen(nvramtool_op.param, "r")) == NULL) { + fprintf(stderr, "%s: Can not open file %s for reading: %s\n", + prog_name, nvramtool_op.param, strerror(errno)); + exit(1); + } + + if ((nr_bytes = fread(data, 1, CMOS_SIZE, f)) != CMOS_SIZE) { + fprintf(stderr, + "%s: Error: Only able to read %d bytes of CMOS data " + "from file %s. CMOS data is unchanged.\n", prog_name, + (int)nr_bytes, nvramtool_op.param); + exit(1); + } + + fclose(f); + set_iopl(3); + cmos_write_all(data); + set_iopl(0); +} + +/**************************************************************************** + * op_show_cmos_hex_dump + * + * -x + * + * Write a hex dump of CMOS memory to standard output. + ****************************************************************************/ +static void op_show_cmos_hex_dump(void) +{ + unsigned char data[CMOS_SIZE]; + + set_iopl(3); + cmos_read_all(data); + set_iopl(0); + hexdump(data, CMOS_SIZE, 0, stdout, &cmos_dump_format); +} + +/**************************************************************************** + * op_show_cmos_dumpfile + * + * -X DUMP_FILE + * + * Read binary data from a file (presumably a CMOS dump file) and display a + * hex dump of the CMOS data from the file. + ****************************************************************************/ +static void op_show_cmos_dumpfile(void) +{ + unsigned char data[CMOS_SIZE]; + size_t nr_bytes; + FILE *f; + + if ((f = fopen(nvramtool_op.param, "r")) == NULL) { + fprintf(stderr, "%s: Can not open file %s for reading: %s\n", + prog_name, nvramtool_op.param, strerror(errno)); + exit(1); + } + + nr_bytes = fread(data, 1, CMOS_SIZE, f); + fclose(f); + hexdump(data, nr_bytes, 0, stdout, &cmos_dump_format); +} + +/**************************************************************************** + * list_one_param + * + * Attempt to list one CMOS parameter given by 'name'. 'show_name' is a + * boolean value indicating whether the parameter name should be displayed + * along with its value. Return 1 if error was encountered. Else return OK. + ****************************************************************************/ +static int list_one_param(const char name[], int show_name) +{ + const cmos_entry_t *e; + + if (is_checksum_name(name) || ((e = find_cmos_entry(name)) == NULL)) { + fprintf(stderr, "%s: CMOS parameter %s not found.\n", prog_name, + name); + exit(1); + } + + if (e->config == CMOS_ENTRY_RESERVED) { + fprintf(stderr, "%s: Parameter %s is reserved.\n", prog_name, + name); + exit(1); + } + + return (list_cmos_entry(e, show_name) != 0); +} + +/**************************************************************************** + * list_all_params + * + * Attempt to list all CMOS parameters. Return 1 if error was encountered. + * Else return OK. + ****************************************************************************/ +static int list_all_params(void) +{ + const cmos_entry_t *e; + int result; + + result = OK; + + for (e = first_cmos_entry(); e != NULL; e = next_cmos_entry(e)) { + if ((e->config == CMOS_ENTRY_RESERVED) + || is_checksum_name(e->name)) + continue; + + if (list_cmos_entry(e, TRUE)) + result = 1; + } + + return result; +} + +/**************************************************************************** + * list_param_enums + * + * List all possible values for CMOS parameter given by 'name'. + ****************************************************************************/ +static void list_param_enums(const char name[]) +{ + const cmos_entry_t *e; + const cmos_enum_t *p; + + if (is_checksum_name(name) || (e = find_cmos_entry(name)) == NULL) { + fprintf(stderr, "%s: CMOS parameter %s not found.\n", prog_name, + name); + exit(1); + } + + switch (e->config) { + case CMOS_ENTRY_ENUM: + for (p = first_cmos_enum_id(e->config_id); + p != NULL; p = next_cmos_enum_id(p)) + printf("%s\n", p->text); + + break; + + case CMOS_ENTRY_HEX: + printf("Parameter %s requires a %u-bit unsigned integer.\n", + name, e->length); + break; + + case CMOS_ENTRY_STRING: + printf("Parameter %s requires a %u-byte string.\n", name, + e->length / 8); + break; + + case CMOS_ENTRY_RESERVED: + printf("Parameter %s is reserved.\n", name); + break; + + default: + BUG(); + } +} + +/**************************************************************************** + * set_one_param + * + * Set the CMOS parameter given by 'name' to 'value'. The 'name' parameter + * is case-sensitive. If we are setting an enum parameter, then 'value' is + * interpreted as a case-sensitive string that must match the option name + * exactly. If we are setting a 'hex' parameter, then 'value' is treated as + * a string representation of an unsigned integer that may be specified in + * decimal, hex, or octal. + ****************************************************************************/ +static void set_one_param(const char name[], const char value[]) +{ + const cmos_entry_t *e; + unsigned long long n; + + if (is_checksum_name(name) || (e = find_cmos_entry(name)) == NULL) { + fprintf(stderr, "%s: CMOS parameter %s not found.", prog_name, + name); + exit(1); + } + + switch (prepare_cmos_write(e, value, &n)) { + case OK: + break; + + case CMOS_OP_BAD_ENUM_VALUE: + fprintf(stderr, "%s: Bad value for parameter %s.", prog_name, + name); + goto fail; + + case CMOS_OP_NEGATIVE_INT: + fprintf(stderr, + "%s: This program does not support assignment of negative " + "numbers to coreboot parameters.", prog_name); + goto fail; + + case CMOS_OP_INVALID_INT: + fprintf(stderr, "%s: %s is not a valid integer.", prog_name, + value); + goto fail; + + case CMOS_OP_RESERVED: + fprintf(stderr, + "%s: Can not modify reserved coreboot parameter %s.", + prog_name, name); + goto fail; + + case CMOS_OP_VALUE_TOO_WIDE: + fprintf(stderr, + "%s: Can not write value %s to CMOS parameter %s that is " + "only %d bits wide.", prog_name, value, name, + e->length); + goto fail; + + case CMOS_OP_NO_MATCHING_ENUM: + fprintf(stderr, + "%s: coreboot parameter %s has no matching enums.", + prog_name, name); + goto fail; + + case CMOS_AREA_OUT_OF_RANGE: + fprintf(stderr, + "%s: The CMOS area specified by the layout info for " + "coreboot parameter %s is out of range.", prog_name, + name); + goto fail; + + case CMOS_AREA_OVERLAPS_RTC: + fprintf(stderr, + "%s: The CMOS area specified by the layout info for " + "coreboot parameter %s overlaps the realtime clock area.", + prog_name, name); + goto fail; + + case CMOS_AREA_TOO_WIDE: + fprintf(stderr, + "%s: The CMOS area specified by the layout info for " + "coreboot parameter %s is too wide.", prog_name, name); + goto fail; + + default: + fprintf(stderr, + "%s: Unknown error encountered while attempting to modify " + "coreboot parameter %s.", prog_name, name); + goto fail; + } + + /* write the value to nonvolatile RAM */ + set_iopl(3); + cmos_write(e, n); + cmos_checksum_write(cmos_checksum_compute()); + set_iopl(0); + return; + + fail: + fprintf(stderr, " CMOS write not performed.\n"); + exit(1); +} + +/**************************************************************************** + * set_params + * + * Set coreboot parameters according to the contents of file 'f'. + ****************************************************************************/ +static void set_params(FILE * f) +{ /* First process the input file. Then perform writes only if there were + * no problems processing the input. Either all values will be written + * successfully or no values will be written. + */ + do_cmos_writes(process_input_file(f)); +} + +/**************************************************************************** + * parse_assignment + * + * Parse the string 'arg' (which supposedly represents an assignment) into a + * NAME and a VALUE. If 'arg' does not conform to the proper assignment + * syntax, exit with a usage message. Otherwise, on return, 'arg' is broken + * into substrings representing NAME and VALUE, and *name and *value are set + * to point to these two substrings. + ****************************************************************************/ +static void parse_assignment(char arg[], const char **name, const char **value) +{ + static const size_t N_MATCHES = 4; + regmatch_t match[N_MATCHES]; + regex_t assignment; + + compile_reg_expr(REG_EXTENDED | REG_NEWLINE, assignment_regex, &assignment); + + /* Does 'arg' conform to proper assignment syntax? If not, exit with a + * usage message. + */ + if (regexec(&assignment, arg, N_MATCHES, match, 0)) + usage(stderr); + + /* Ok, we found a valid assignment. Break it into two strings + * representing NAME and VALUE. + */ + arg[match[1].rm_eo] = '\0'; + arg[match[2].rm_eo] = '\0'; + *name = &arg[match[1].rm_so]; + *value = &arg[match[2].rm_so]; + + regfree(&assignment); +} + +/**************************************************************************** + * list_cmos_entry + * + * Attempt to list the CMOS entry represented by 'e'. 'show_name' is a + * boolean value indicating whether the parameter name should be displayed + * along with its value. On success, return OK. On error, print an error + * message and return 1. + ****************************************************************************/ +static int list_cmos_entry(const cmos_entry_t * e, int show_name) +{ + const cmos_enum_t *p; + unsigned long long value; + char *w; + + /* sanity check CMOS entry */ + switch (prepare_cmos_read(e)) { + case OK: + break; + + case CMOS_OP_RESERVED: + BUG(); + + case CMOS_AREA_OUT_OF_RANGE: + fprintf(stderr, + "%s: Can not read coreboot parameter %s because " + "layout info specifies out of range CMOS area.\n", + prog_name, e->name); + return 1; + + case CMOS_AREA_OVERLAPS_RTC: + fprintf(stderr, + "%s: Can not read coreboot parameter %s because " + "layout info specifies CMOS area that overlaps realtime " + "clock area.\n", prog_name, e->name); + return 1; + + case CMOS_AREA_TOO_WIDE: + fprintf(stderr, + "%s: Can not read coreboot parameter %s because " + "layout info specifies CMOS area that is too wide.\n", + prog_name, e->name); + return 1; + + default: + fprintf(stderr, + "%s: Unknown error encountered while attempting to " + "read coreboot parameter %s\n", prog_name, e->name); + return 1; + } + + /* read the value from CMOS */ + set_iopl(3); + value = cmos_read(e); + set_iopl(0); + + /* display the value */ + switch (e->config) { + case CMOS_ENTRY_ENUM: + if ((p = find_cmos_enum(e->config_id, value)) == NULL) { + if (show_name) + printf("# Bad value -> %s = 0x%llx\n", e->name, + value); + else + printf("Bad value -> 0x%llx\n", value); + } else { + if (show_name) + printf("%s = %s\n", e->name, p->text); + else + printf("%s\n", p->text); + } + + break; + + case CMOS_ENTRY_HEX: + if (show_name) + printf("%s = 0x%llx\n", e->name, value); + else + printf("0x%llx\n", value); + + break; + + case CMOS_ENTRY_STRING: + w = (char *)(unsigned long)value; + while (*w) { + if(!isprint(*w)) { + if (show_name) + printf("# Bad value -> %s\n", e->name); + else + printf("Bad value\n"); + break; + } + w++; + } + + if (!*w) { + + if (show_name) + printf("%s = %s\n", e->name, + (char *)(unsigned long)value); + else + printf("%s\n", (char *)(unsigned long)value); + } + + free((void *)(unsigned long)value); + + break; + + case CMOS_ENTRY_RESERVED: + default: + BUG(); + } + + return OK; +} + +/**************************************************************************** + * convert_checksum_value + * + * 'value' is the string representation of a checksum value that the user + * wishes to set using the -c option. Convert the string to a 16-bit + * unsigned integer and return the result. Exit with an error message if + * 'value' is invalid. + ****************************************************************************/ +static uint16_t convert_checksum_value(const char value[]) +{ + unsigned long n; + const char *p; + uint16_t result; + int negative; + + for (p = value; isspace(*p); p++) ; + + negative = (*p == '-'); + n = strtoul(value, (char **)&p, 0); + + if (*p) { + fprintf(stderr, + "%s: Checksum value %s is not a valid integer.\n", + prog_name, value); + exit(1); + } + + if (negative) { + fprintf(stderr, + "%s: Checksum must be an unsigned integer.\n", + prog_name); + exit(1); + } + + result = (uint16_t) n; + + if (result != n) { + fprintf(stderr, + "%s: Checksum value must fit within 16 bits.\n", + prog_name); + exit(1); + } + + return result; +} diff --git a/util/nvramtool/cli/opts.c b/util/nvramtool/cli/opts.c new file mode 100644 index 0000000000..49496495eb --- /dev/null +++ b/util/nvramtool/cli/opts.c @@ -0,0 +1,259 @@ +/*****************************************************************************\ + * opts.c + ***************************************************************************** + * Copyright (C) 2002-2005 The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * Written by Dave Peterson <dsp@llnl.gov> <dave_peterson@pobox.com>. + * UCRL-CODE-2003-012 + * All rights reserved. + * + * This file is part of nvramtool, a utility for reading/writing coreboot + * parameters and displaying information from the coreboot table. + * For details, see http://coreboot.org/nvramtool. + * + * Please also read the file DISCLAIMER which is included in this software + * distribution. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License (as published by the + * Free Software Foundation) version 2, dated June 1991. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY OF + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the terms and + * conditions of the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +\*****************************************************************************/ + +#include "common.h" +#include "opts.h" + +nvramtool_op_info_t nvramtool_op; + +nvramtool_op_modifier_info_t nvramtool_op_modifiers[NVRAMTOOL_NUM_OP_MODIFIERS]; + +static char *handle_optional_arg(int argc, char *argv[]); +static void register_op(int *op_found, nvramtool_op_t op, char op_param[]); +static void register_op_modifier(nvramtool_op_modifier_t mod, char mod_param[]); +static void resolve_op_modifiers(void); +static void sanity_check_args(void); + +static const char getopt_string[] = "-ab:B:c::C:dD:e:hil::np:r:tvw:xX:y:Y"; + +/**************************************************************************** + * parse_nvramtool_args + * + * Parse command line arguments. + ****************************************************************************/ +void parse_nvramtool_args(int argc, char *argv[]) +{ + nvramtool_op_modifier_info_t *mod_info; + int i, op_found; + char c; + + for (i = 0, mod_info = nvramtool_op_modifiers; + i < NVRAMTOOL_NUM_OP_MODIFIERS; i++, mod_info++) { + mod_info->found = FALSE; + mod_info->found_seq = 0; + mod_info->param = NULL; + } + + op_found = FALSE; + opterr = 0; + + do { + switch (c = getopt(argc, argv, getopt_string)) { + case 'a': + register_op(&op_found, + NVRAMTOOL_OP_CMOS_SHOW_ALL_PARAMS, NULL); + break; + case 'b': + register_op(&op_found, NVRAMTOOL_OP_WRITE_CMOS_DUMP, + optarg); + break; + case 'B': + register_op(&op_found, NVRAMTOOL_OP_READ_CMOS_DUMP, + optarg); + break; + case 'c': + register_op(&op_found, NVRAMTOOL_OP_CMOS_CHECKSUM, + handle_optional_arg(argc, argv)); + break; + case 'C': + register_op_modifier(NVRAMTOOL_MOD_USE_CBFS_FILE, + optarg); + break; + case 'd': + register_op(&op_found, NVRAMTOOL_OP_LBTABLE_DUMP, NULL); + break; + case 'D': + register_op_modifier(NVRAMTOOL_MOD_USE_CMOS_FILE, + optarg); + break; + case 'e': + register_op(&op_found, NVRAMTOOL_OP_SHOW_PARAM_VALUES, + optarg); + break; + case 'h': + register_op(&op_found, NVRAMTOOL_OP_SHOW_USAGE, NULL); + break; + case 'i': + register_op(&op_found, + NVRAMTOOL_OP_CMOS_SET_PARAMS_STDIN, NULL); + break; + case 'l': + register_op(&op_found, NVRAMTOOL_OP_LBTABLE_SHOW_INFO, + handle_optional_arg(argc, argv)); + break; + case 'n': + register_op_modifier(NVRAMTOOL_MOD_SHOW_VALUE_ONLY, + NULL); + break; + case 'p': + register_op(&op_found, + NVRAMTOOL_OP_CMOS_SET_PARAMS_FILE, optarg); + break; + case 'r': + register_op(&op_found, NVRAMTOOL_OP_CMOS_SHOW_ONE_PARAM, + optarg); + break; + case 't': + register_op_modifier(NVRAMTOOL_MOD_USE_CMOS_OPT_TABLE, + NULL); + break; + case 'v': + register_op(&op_found, NVRAMTOOL_OP_SHOW_VERSION, NULL); + break; + case 'w': + register_op(&op_found, NVRAMTOOL_OP_CMOS_SET_ONE_PARAM, + optarg); + break; + case 'x': + register_op(&op_found, NVRAMTOOL_OP_SHOW_CMOS_HEX_DUMP, + NULL); + break; + case 'X': + register_op(&op_found, NVRAMTOOL_OP_SHOW_CMOS_DUMPFILE, + optarg); + break; + case 'y': + register_op_modifier(NVRAMTOOL_MOD_USE_CMOS_LAYOUT_FILE, + optarg); + break; + case 'Y': + register_op(&op_found, NVRAMTOOL_OP_SHOW_LAYOUT, NULL); + break; + case -1: /* no more command line args */ + break; + case '?': /* unknown option found */ + case 1: /* nonoption command line arg found */ + default: + usage(stderr); + break; + } + } while (c != -1); + + if (!op_found) + usage(stderr); + + resolve_op_modifiers(); + sanity_check_args(); +} + +/**************************************************************************** + * handle_optional_arg + * + * Handle a command line option with an optional argument. + ****************************************************************************/ +static char *handle_optional_arg(int argc, char *argv[]) +{ + char *arg; + + if (optarg != NULL) { + /* optional arg is present and arg was specified as + * "-zarg" (with no whitespace between "z" and "arg"), + * where -z is the option and "arg" is the value of the + * optional arg + */ + return optarg; + } + + if ((argv[optind] == NULL) || (argv[optind][0] == '-')) + return NULL; + + arg = argv[optind]; /* optional arg is present */ + + /* This call to getopt yields the optional arg we just found, + * which we want to skip. + */ + getopt(argc, argv, getopt_string); + + return arg; +} + +/**************************************************************************** + * register_op + * + * Store the user's selection of which operation this program should perform. + ****************************************************************************/ +static void register_op(int *op_found, nvramtool_op_t op, char op_param[]) +{ + if (*op_found && (op != nvramtool_op.op)) + usage(stderr); + + *op_found = TRUE; + nvramtool_op.op = op; + nvramtool_op.param = op_param; +} + +/**************************************************************************** + * register_op_modifier + * + * Store information regarding an optional argument specified in addition to + * the user's selection of which operation this program should perform. + ****************************************************************************/ +static void register_op_modifier(nvramtool_op_modifier_t mod, char mod_param[]) +{ + static int found_seq = 0; + nvramtool_op_modifier_info_t *mod_info; + + mod_info = &nvramtool_op_modifiers[mod]; + mod_info->found = TRUE; + mod_info->found_seq = ++found_seq; + mod_info->param = mod_param; +} + +/**************************************************************************** + * resolve_op_modifiers + * + * If the user specifies multiple arguments that conflict with each other, + * the last specified argument overrides previous conflicting arguments. + ****************************************************************************/ +static void resolve_op_modifiers(void) +{ + if (nvramtool_op_modifiers[NVRAMTOOL_MOD_USE_CMOS_LAYOUT_FILE].found && + nvramtool_op_modifiers[NVRAMTOOL_MOD_USE_CMOS_OPT_TABLE].found) { + if (nvramtool_op_modifiers[NVRAMTOOL_MOD_USE_CMOS_LAYOUT_FILE].found_seq > + nvramtool_op_modifiers[NVRAMTOOL_MOD_USE_CMOS_OPT_TABLE].found_seq) + nvramtool_op_modifiers + [NVRAMTOOL_MOD_USE_CMOS_OPT_TABLE].found = FALSE; + else + nvramtool_op_modifiers + [NVRAMTOOL_MOD_USE_CMOS_LAYOUT_FILE].found = FALSE; + } +} + +/**************************************************************************** + * sanity_check_args + * + * Perform sanity checking on command line arguments. + ****************************************************************************/ +static void sanity_check_args(void) +{ + if ((nvramtool_op_modifiers[NVRAMTOOL_MOD_SHOW_VALUE_ONLY].found) && + (nvramtool_op.op != NVRAMTOOL_OP_CMOS_SHOW_ONE_PARAM)) + usage(stderr); +} diff --git a/util/nvramtool/cli/opts.h b/util/nvramtool/cli/opts.h new file mode 100644 index 0000000000..f46f254b88 --- /dev/null +++ b/util/nvramtool/cli/opts.h @@ -0,0 +1,79 @@ +/*****************************************************************************\ + * opts.h + ***************************************************************************** + * Copyright (C) 2002-2005 The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * Written by Dave Peterson <dsp@llnl.gov> <dave_peterson@pobox.com>. + * UCRL-CODE-2003-012 + * All rights reserved. + * + * This file is part of nvramtool, a utility for reading/writing coreboot + * parameters and displaying information from the coreboot table. + * For details, see http://coreboot.org/nvramtool. + * + * Please also read the file DISCLAIMER which is included in this software + * distribution. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License (as published by the + * Free Software Foundation) version 2, dated June 1991. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY OF + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the terms and + * conditions of the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +\*****************************************************************************/ + +#ifndef OPTS_H +#define OPTS_H + +#include "common.h" + +typedef enum { NVRAMTOOL_OP_SHOW_VERSION = 0, + NVRAMTOOL_OP_SHOW_USAGE, + NVRAMTOOL_OP_LBTABLE_SHOW_INFO, + NVRAMTOOL_OP_LBTABLE_DUMP, + NVRAMTOOL_OP_SHOW_PARAM_VALUES, + NVRAMTOOL_OP_CMOS_SHOW_ONE_PARAM, + NVRAMTOOL_OP_CMOS_SHOW_ALL_PARAMS, + NVRAMTOOL_OP_CMOS_SET_ONE_PARAM, + NVRAMTOOL_OP_CMOS_SET_PARAMS_STDIN, + NVRAMTOOL_OP_CMOS_SET_PARAMS_FILE, + NVRAMTOOL_OP_CMOS_CHECKSUM, + NVRAMTOOL_OP_SHOW_LAYOUT, + NVRAMTOOL_OP_WRITE_CMOS_DUMP, + NVRAMTOOL_OP_READ_CMOS_DUMP, + NVRAMTOOL_OP_SHOW_CMOS_HEX_DUMP, + NVRAMTOOL_OP_SHOW_CMOS_DUMPFILE +} nvramtool_op_t; + +typedef struct { + nvramtool_op_t op; + char *param; +} nvramtool_op_info_t; + +typedef enum { NVRAMTOOL_MOD_SHOW_VALUE_ONLY = 0, + NVRAMTOOL_MOD_USE_CMOS_LAYOUT_FILE, + NVRAMTOOL_MOD_USE_CBFS_FILE, + NVRAMTOOL_MOD_USE_CMOS_FILE, + NVRAMTOOL_MOD_USE_CMOS_OPT_TABLE, + NVRAMTOOL_NUM_OP_MODIFIERS /* must always be last */ +} nvramtool_op_modifier_t; + +typedef struct { + int found; + int found_seq; + char *param; +} nvramtool_op_modifier_info_t; + +extern nvramtool_op_info_t nvramtool_op; + +extern nvramtool_op_modifier_info_t nvramtool_op_modifiers[]; + +void parse_nvramtool_args(int argc, char *argv[]); + +#endif /* OPTS_H */ |