soc/intel/cmn/cse: Deprecate CONFIG_SOC_INTEL_CSE_RW_VERSION
[coreboot2.git] / util / nvramtool / cli / nvramtool.c
blob046bd9b602688246498be333f8a95b214482e9c6
1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <fcntl.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #ifndef __MINGW32__
7 #include <sys/mman.h>
8 #endif
9 #include "common.h"
10 #include "opts.h"
11 #include "lbtable.h"
12 #include "layout.h"
13 #include "accessors/layout-text.h"
14 #include "input_file.h"
15 #include "cmos_ops.h"
16 #include "cmos_lowlevel.h"
17 #include "reg_expr.h"
18 #include "hexdump.h"
19 #include "cbfs.h"
20 #ifdef __MINGW32__
21 #include <windows.h>
22 #endif
24 typedef void (*op_fn_t) (void);
26 static void op_show_version(void);
27 static void op_show_usage(void);
28 static void op_lbtable_show_info(void);
29 static void op_lbtable_dump(void);
30 static void op_show_param_values(void);
31 static void op_cmos_show_one_param(void);
32 static void op_cmos_show_all_params(void);
33 static void op_cmos_set_one_param(void);
34 static void op_cmos_set_params_stdin(void);
35 static void op_cmos_set_params_file(void);
36 static void op_cmos_checksum(void);
37 static void op_show_layout(void);
38 static void op_write_cmos_dump(void);
39 static void op_read_cmos_dump(void);
40 static void op_show_cmos_hex_dump(void);
41 static void op_show_cmos_dumpfile(void);
42 static void op_write_cmos_layout_bin(void);
43 static void op_write_cmos_layout_header(void);
44 static int list_one_param(const char name[], int show_name);
45 static int list_all_params(void);
46 static void list_param_enums(const char name[]);
47 static void set_one_param(const char name[], const char value[]);
48 static void set_params(FILE * f);
49 static void parse_assignment(char arg[], const char **name, const char **value);
50 static int list_cmos_entry(const cmos_entry_t * e, int show_name);
51 static uint16_t convert_checksum_value(const char value[]);
53 static const op_fn_t op_fns[] = { op_show_version,
54 op_show_usage,
55 op_lbtable_show_info,
56 op_lbtable_dump,
57 op_show_param_values,
58 op_cmos_show_one_param,
59 op_cmos_show_all_params,
60 op_cmos_set_one_param,
61 op_cmos_set_params_stdin,
62 op_cmos_set_params_file,
63 op_cmos_checksum,
64 op_show_layout,
65 op_write_cmos_dump,
66 op_read_cmos_dump,
67 op_show_cmos_hex_dump,
68 op_show_cmos_dumpfile,
69 op_write_cmos_layout_bin,
70 op_write_cmos_layout_header
73 static void op_write_cmos_layout_bin(void)
75 get_layout_from_file();
76 write_cmos_output_bin(nvramtool_op.param);
79 static void op_write_cmos_layout_header(void)
81 get_layout_from_file();
82 write_cmos_layout_header(nvramtool_op.param);
85 static const hexdump_format_t cmos_dump_format =
86 { 16, 2, "", " | ", " ", " | ", '.' };
88 /****************************************************************************
89 * main
90 ****************************************************************************/
91 int main(int argc, char *argv[])
93 void *cmos_default = NULL;
94 cmos_layout_get_fn_t fn = get_layout_from_cmos_table;
96 parse_nvramtool_args(argc, argv);
98 /* If we should operate on a CBFS file default to reading the layout
99 * and CMOS contents from it. */
100 if (nvramtool_op_modifiers[NVRAMTOOL_MOD_USE_CBFS_FILE].found) {
101 open_cbfs(nvramtool_op_modifiers[NVRAMTOOL_MOD_USE_CBFS_FILE].param);
102 if (!nvramtool_op_modifiers[NVRAMTOOL_MOD_USE_CMOS_FILE].found) {
103 cmos_default = cbfs_find_file("cmos.default", CBFS_COMPONENT_CMOS_DEFAULT, NULL);
104 if (cmos_default == NULL) {
105 fprintf(stderr, "Need a cmos.default in the CBFS image or separate CMOS file (-D).\n");
106 exit(1);
109 fn = get_layout_from_cbfs_file;
112 /* If the user wants to use a specific layout file or explicitly use
113 * the coreboot option table allow him to override previous settings. */
114 if (nvramtool_op_modifiers[NVRAMTOOL_MOD_USE_CMOS_LAYOUT_FILE].found) {
115 set_layout_filename(nvramtool_op_modifiers[NVRAMTOOL_MOD_USE_CMOS_LAYOUT_FILE].param);
116 fn = get_layout_from_file;
117 } else if (nvramtool_op_modifiers[NVRAMTOOL_MOD_USE_CMOS_OPT_TABLE].found) {
118 fn = get_layout_from_cmos_table;
121 /* Allow the user to use a file for the CMOS contents, possibly
122 * overriding a previously opened "cmos.default" file from the CBFS. */
123 if (nvramtool_op_modifiers[NVRAMTOOL_MOD_USE_CMOS_FILE].found) {
124 struct stat fd_stat;
125 int fd;
127 if ((fd = open(nvramtool_op_modifiers[NVRAMTOOL_MOD_USE_CMOS_FILE].param, O_RDWR | O_CREAT, 0666)) < 0) {
128 fprintf(stderr, "Couldn't open '%s'\n", nvramtool_op_modifiers[NVRAMTOOL_MOD_USE_CMOS_FILE].param);
129 exit(1);
132 if (fstat(fd, &fd_stat) == -1) {
133 fprintf(stderr, "Couldn't stat '%s'\n", nvramtool_op_modifiers[NVRAMTOOL_MOD_USE_CMOS_FILE].param);
134 exit(1);
137 if (fd_stat.st_size < CMOS_SIZE) {
138 if ((lseek(fd, CMOS_SIZE - 1, SEEK_SET) == -1) ||
139 (write(fd, "\0", 1) != 1)) {
140 fprintf(stderr, "Unable to extended '%s' to its full size.\n",
141 nvramtool_op_modifiers[NVRAMTOOL_MOD_USE_CMOS_FILE].param);
142 exit(1);
144 #ifndef __MINGW32__
145 fsync(fd);
146 #else
147 FlushFileBuffers ((HANDLE) _get_osfhandle (fd));
148 #endif
151 cmos_default = mmap(NULL, CMOS_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
152 if (cmos_default == MAP_FAILED) {
153 fprintf(stderr, "Couldn't map '%s'\n", nvramtool_op_modifiers[NVRAMTOOL_MOD_USE_CMOS_FILE].param);
154 exit(1);
158 /* Switch to memory based CMOS access. */
159 if (cmos_default) {
160 select_hal(HAL_MEMORY, cmos_default);
163 register_cmos_layout_get_fn(fn);
164 op_fns[nvramtool_op.op]();
166 return 0;
169 /****************************************************************************
170 * op_show_version
172 * -v
174 * Show version information for this program.
175 ****************************************************************************/
176 static void op_show_version(void)
178 printf("This is %s version %s.\n", prog_name, prog_version);
181 /****************************************************************************
182 * op_show_usage
184 * -h
186 * Show a usage message for this program.
187 ****************************************************************************/
188 static void op_show_usage(void)
190 usage(stdout);
193 /****************************************************************************
194 * op_lbtable_show_info
196 * -l [ARG]
198 * If ARG is present, show coreboot table information specified by ARG.
199 * Else show all possible values for ARG.
200 ****************************************************************************/
201 static void op_lbtable_show_info(void)
203 if (nvramtool_op.param == NULL)
204 list_lbtable_choices();
205 else {
206 get_lbtable();
207 list_lbtable_item(nvramtool_op.param);
211 /****************************************************************************
212 * op_lbtable_dump
214 * -d
216 * Do low-level dump of coreboot table.
217 ****************************************************************************/
218 static void op_lbtable_dump(void)
220 get_lbtable();
221 dump_lbtable();
224 /****************************************************************************
225 * op_show_param_values
227 * -e NAME option
229 * Show all possible values for parameter NAME.
230 ****************************************************************************/
231 static void op_show_param_values(void)
233 get_cmos_layout();
234 list_param_enums(nvramtool_op.param);
237 /****************************************************************************
238 * op_cmos_show_one_param
240 * [-n] -r NAME
242 * Show parameter NAME. If -n is specified, show value only. Else show name
243 * and value.
244 ****************************************************************************/
245 static void op_cmos_show_one_param(void)
247 int result;
249 get_cmos_layout();
250 result = list_one_param(nvramtool_op.param,
251 !nvramtool_op_modifiers
252 [NVRAMTOOL_MOD_SHOW_VALUE_ONLY].found);
253 cmos_checksum_verify();
255 if (result)
256 exit(1);
259 /****************************************************************************
260 * op_cmos_show_all_params
262 * -a
264 * Show names and values for all parameters.
265 ****************************************************************************/
266 static void op_cmos_show_all_params(void)
268 int result;
270 get_cmos_layout();
271 result = list_all_params();
272 cmos_checksum_verify();
274 if (result)
275 exit(1);
278 /****************************************************************************
279 * op_cmos_set_one_param
281 * -w NAME=VALUE
283 * Set parameter NAME to VALUE.
284 ****************************************************************************/
285 static void op_cmos_set_one_param(void)
287 const char *name, *value;
289 get_cmos_layout();
291 /* Separate 'NAME=VALUE' syntax into two strings representing NAME and
292 * VALUE.
294 parse_assignment(nvramtool_op.param, &name, &value);
296 set_one_param(name, value);
299 /****************************************************************************
300 * op_cmos_set_params_stdin
302 * -i
304 * Set parameters according to standard input.
305 ****************************************************************************/
306 static void op_cmos_set_params_stdin(void)
308 get_cmos_layout();
309 set_params(stdin);
312 /****************************************************************************
313 * op_cmos_set_params_file
315 * -p INPUT_FILE
317 * Set parameters according to INPUT_FILE.
318 ****************************************************************************/
319 static void op_cmos_set_params_file(void)
321 FILE *f;
323 if ((f = fopen(nvramtool_op.param, "r")) == NULL) {
324 fprintf(stderr, "%s: Can not open file %s for reading: %s\n",
325 prog_name, nvramtool_op.param, strerror(errno));
326 exit(1);
329 get_cmos_layout();
330 set_params(f);
331 fclose(f);
334 /****************************************************************************
335 * op_cmos_checksum
337 * -c [VALUE]
339 * If VALUE is present, set coreboot CMOS checksum to VALUE. Else show
340 * checksum value.
341 ****************************************************************************/
342 static void op_cmos_checksum(void)
344 uint16_t checksum;
346 get_cmos_layout();
348 if (nvramtool_op.param == NULL) {
349 set_iopl(3);
350 checksum = cmos_checksum_read();
351 set_iopl(0);
352 printf("0x%x\n", checksum);
353 } else {
354 checksum = convert_checksum_value(nvramtool_op.param);
355 set_iopl(3);
356 cmos_checksum_write(checksum);
357 set_iopl(0);
361 /****************************************************************************
362 * op_show_layout
364 * -Y
366 * Write CMOS layout information to standard output.
367 ****************************************************************************/
368 static void op_show_layout(void)
370 get_cmos_layout();
371 write_cmos_layout(stdout);
374 /****************************************************************************
375 * op_write_cmos_dump
377 * -b OUTPUT_FILE
379 * Write the contents of CMOS memory to a binary file.
380 ****************************************************************************/
381 static void op_write_cmos_dump(void)
383 unsigned char data[CMOS_SIZE];
384 FILE *f;
386 if ((f = fopen(nvramtool_op.param, "wb")) == NULL) {
387 fprintf(stderr, "%s: Can not open file %s for writing: %s\n",
388 prog_name, nvramtool_op.param, strerror(errno));
389 exit(1);
392 set_iopl(3);
393 cmos_read_all(data);
394 set_iopl(0);
396 if (fwrite(data, 1, CMOS_SIZE, f) != CMOS_SIZE) {
397 fprintf(stderr, "%s: Error writing CMOS data to file %s: %s\n",
398 prog_name, nvramtool_op.param, strerror(errno));
399 exit(1);
402 fclose(f);
405 /****************************************************************************
406 * op_read_cmos_dump
408 * -B INPUT_FILE
410 * Read binary data from a file and write the data to CMOS memory.
411 ****************************************************************************/
412 static void op_read_cmos_dump(void)
414 unsigned char data[CMOS_SIZE];
415 size_t nr_bytes;
416 FILE *f;
418 if ((f = fopen(nvramtool_op.param, "rb")) == NULL) {
419 fprintf(stderr, "%s: Can not open file %s for reading: %s\n",
420 prog_name, nvramtool_op.param, strerror(errno));
421 exit(1);
424 if ((nr_bytes = fread(data, 1, CMOS_SIZE, f)) != CMOS_SIZE) {
425 fprintf(stderr,
426 "%s: Error: Only able to read %d bytes of CMOS data "
427 "from file %s. CMOS data is unchanged.\n", prog_name,
428 (int)nr_bytes, nvramtool_op.param);
429 exit(1);
432 fclose(f);
433 set_iopl(3);
434 cmos_write_all(data);
435 set_iopl(0);
438 /****************************************************************************
439 * op_show_cmos_hex_dump
441 * -x
443 * Write a hex dump of CMOS memory to standard output.
444 ****************************************************************************/
445 static void op_show_cmos_hex_dump(void)
447 unsigned char data[CMOS_SIZE];
449 set_iopl(3);
450 cmos_read_all(data);
451 set_iopl(0);
452 hexdump(data, CMOS_SIZE, 0, stdout, &cmos_dump_format);
455 /****************************************************************************
456 * op_show_cmos_dumpfile
458 * -X DUMP_FILE
460 * Read binary data from a file (presumably a CMOS dump file) and display a
461 * hex dump of the CMOS data from the file.
462 ****************************************************************************/
463 static void op_show_cmos_dumpfile(void)
465 unsigned char data[CMOS_SIZE];
466 size_t nr_bytes;
467 FILE *f;
469 if ((f = fopen(nvramtool_op.param, "r")) == NULL) {
470 fprintf(stderr, "%s: Can not open file %s for reading: %s\n",
471 prog_name, nvramtool_op.param, strerror(errno));
472 exit(1);
475 nr_bytes = fread(data, 1, CMOS_SIZE, f);
476 fclose(f);
477 hexdump(data, nr_bytes, 0, stdout, &cmos_dump_format);
480 /****************************************************************************
481 * list_one_param
483 * Attempt to list one CMOS parameter given by 'name'. 'show_name' is a
484 * boolean value indicating whether the parameter name should be displayed
485 * along with its value. Return 1 if error was encountered. Else return OK.
486 ****************************************************************************/
487 static int list_one_param(const char name[], int show_name)
489 const cmos_entry_t *e;
491 if (is_checksum_name(name) || ((e = find_cmos_entry(name)) == NULL)) {
492 fprintf(stderr, "%s: CMOS parameter %s not found.\n", prog_name,
493 name);
494 exit(1);
497 if (e->config == CMOS_ENTRY_RESERVED) {
498 fprintf(stderr, "%s: Parameter %s is reserved.\n", prog_name,
499 name);
500 exit(1);
503 return (list_cmos_entry(e, show_name) != 0);
506 /****************************************************************************
507 * list_all_params
509 * Attempt to list all CMOS parameters. Return 1 if error was encountered.
510 * Else return OK.
511 ****************************************************************************/
512 static int list_all_params(void)
514 const cmos_entry_t *e;
515 int result;
517 result = OK;
519 for (e = first_cmos_entry(); e != NULL; e = next_cmos_entry(e)) {
520 if ((e->config == CMOS_ENTRY_RESERVED)
521 || is_checksum_name(e->name))
522 continue;
524 if (list_cmos_entry(e, TRUE))
525 result = 1;
528 return result;
531 /****************************************************************************
532 * list_param_enums
534 * List all possible values for CMOS parameter given by 'name'.
535 ****************************************************************************/
536 static void list_param_enums(const char name[])
538 const cmos_entry_t *e;
539 const cmos_enum_t *p;
541 if (is_checksum_name(name) || (e = find_cmos_entry(name)) == NULL) {
542 fprintf(stderr, "%s: CMOS parameter %s not found.\n", prog_name,
543 name);
544 exit(1);
547 switch (e->config) {
548 case CMOS_ENTRY_ENUM:
549 for (p = first_cmos_enum_id(e->config_id);
550 p != NULL; p = next_cmos_enum_id(p))
551 printf("%s\n", p->text);
553 break;
555 case CMOS_ENTRY_HEX:
556 printf("Parameter %s requires a %u-bit unsigned integer.\n",
557 name, e->length);
558 break;
560 case CMOS_ENTRY_STRING:
561 printf("Parameter %s requires a %u-byte string.\n", name,
562 e->length / 8);
563 break;
565 case CMOS_ENTRY_RESERVED:
566 printf("Parameter %s is reserved.\n", name);
567 break;
569 default:
570 BUG();
574 /****************************************************************************
575 * set_one_param
577 * Set the CMOS parameter given by 'name' to 'value'. The 'name' parameter
578 * is case-sensitive. If we are setting an enum parameter, then 'value' is
579 * interpreted as a case-sensitive string that must match the option name
580 * exactly. If we are setting a 'hex' parameter, then 'value' is treated as
581 * a string representation of an unsigned integer that may be specified in
582 * decimal, hex, or octal.
583 ****************************************************************************/
584 static void set_one_param(const char name[], const char value[])
586 const cmos_entry_t *e;
587 unsigned long long n;
589 if (is_checksum_name(name) || (e = find_cmos_entry(name)) == NULL) {
590 fprintf(stderr, "%s: CMOS parameter %s not found.\n", prog_name,
591 name);
592 exit(1);
595 switch (prepare_cmos_write(e, value, &n)) {
596 case OK:
597 break;
599 case CMOS_OP_BAD_ENUM_VALUE:
600 fprintf(stderr, "%s: Bad value for parameter %s.", prog_name,
601 name);
602 goto fail;
604 case CMOS_OP_NEGATIVE_INT:
605 fprintf(stderr,
606 "%s: This program does not support assignment of negative "
607 "numbers to coreboot parameters.", prog_name);
608 goto fail;
610 case CMOS_OP_INVALID_INT:
611 fprintf(stderr, "%s: %s is not a valid integer.", prog_name,
612 value);
613 goto fail;
615 case CMOS_OP_RESERVED:
616 fprintf(stderr,
617 "%s: Can not modify reserved coreboot parameter %s.",
618 prog_name, name);
619 goto fail;
621 case CMOS_OP_VALUE_TOO_WIDE:
622 fprintf(stderr,
623 "%s: Can not write value %s to CMOS parameter %s that is "
624 "only %d bits wide.", prog_name, value, name,
625 e->length);
626 goto fail;
628 case CMOS_OP_NO_MATCHING_ENUM:
629 fprintf(stderr,
630 "%s: coreboot parameter %s has no matching enums.",
631 prog_name, name);
632 goto fail;
634 case CMOS_AREA_OUT_OF_RANGE:
635 fprintf(stderr,
636 "%s: The CMOS area specified by the layout info for "
637 "coreboot parameter %s is out of range.", prog_name,
638 name);
639 goto fail;
641 case CMOS_AREA_OVERLAPS_RTC:
642 fprintf(stderr,
643 "%s: The CMOS area specified by the layout info for "
644 "coreboot parameter %s overlaps the realtime clock area.",
645 prog_name, name);
646 goto fail;
648 case CMOS_AREA_TOO_WIDE:
649 fprintf(stderr,
650 "%s: The CMOS area specified by the layout info for "
651 "coreboot parameter %s is too wide.", prog_name, name);
652 goto fail;
654 default:
655 fprintf(stderr,
656 "%s: Unknown error encountered while attempting to modify "
657 "coreboot parameter %s.", prog_name, name);
658 goto fail;
661 /* write the value to nonvolatile RAM */
662 set_iopl(3);
663 cmos_write(e, n);
664 cmos_checksum_write(cmos_checksum_compute());
665 set_iopl(0);
666 return;
668 fail:
669 fprintf(stderr, " CMOS write not performed.\n");
670 exit(1);
673 /****************************************************************************
674 * set_params
676 * Set coreboot parameters according to the contents of file 'f'.
677 ****************************************************************************/
678 static void set_params(FILE * f)
679 { /* First process the input file. Then perform writes only if there were
680 * no problems processing the input. Either all values will be written
681 * successfully or no values will be written.
683 do_cmos_writes(process_input_file(f));
686 /****************************************************************************
687 * parse_assignment
689 * Parse the string 'arg' (which supposedly represents an assignment) into a
690 * NAME and a VALUE. If 'arg' does not conform to the proper assignment
691 * syntax, exit with a usage message. Otherwise, on return, 'arg' is broken
692 * into substrings representing NAME and VALUE, and *name and *value are set
693 * to point to these two substrings.
694 ****************************************************************************/
695 static void parse_assignment(char arg[], const char **name, const char **value)
697 static const size_t N_MATCHES = 4;
698 regmatch_t match[N_MATCHES];
699 regex_t assignment;
701 compile_reg_expr(REG_EXTENDED | REG_NEWLINE, assignment_regex, &assignment);
703 /* Does 'arg' conform to proper assignment syntax? If not, exit with a
704 * usage message.
706 if (regexec(&assignment, arg, N_MATCHES, match, 0))
707 usage(stderr);
709 /* Ok, we found a valid assignment. Break it into two strings
710 * representing NAME and VALUE.
712 arg[match[1].rm_eo] = '\0';
713 arg[match[2].rm_eo] = '\0';
714 *name = &arg[match[1].rm_so];
715 *value = &arg[match[2].rm_so];
717 regfree(&assignment);
720 /****************************************************************************
721 * list_cmos_entry
723 * Attempt to list the CMOS entry represented by 'e'. 'show_name' is a
724 * boolean value indicating whether the parameter name should be displayed
725 * along with its value. On success, return OK. On error, print an error
726 * message and return 1.
727 ****************************************************************************/
728 static int list_cmos_entry(const cmos_entry_t * e, int show_name)
730 const cmos_enum_t *p;
731 unsigned long long value;
732 char *w;
734 /* sanity check CMOS entry */
735 switch (prepare_cmos_read(e)) {
736 case OK:
737 break;
739 case CMOS_OP_RESERVED:
740 fprintf(stderr,
741 "%s: Cannot access reserved CMOS area (for %s).\n",
742 prog_name, e->name);
743 return 1;
745 case CMOS_AREA_OUT_OF_RANGE:
746 fprintf(stderr,
747 "%s: Can not read coreboot parameter %s because "
748 "layout info specifies out of range CMOS area.\n",
749 prog_name, e->name);
750 return 1;
752 case CMOS_AREA_OVERLAPS_RTC:
753 fprintf(stderr,
754 "%s: Can not read coreboot parameter %s because "
755 "layout info specifies CMOS area that overlaps realtime "
756 "clock area.\n", prog_name, e->name);
757 return 1;
759 case CMOS_AREA_TOO_WIDE:
760 fprintf(stderr,
761 "%s: Can not read coreboot parameter %s because "
762 "layout info specifies CMOS area that is too wide.\n",
763 prog_name, e->name);
764 return 1;
766 default:
767 fprintf(stderr,
768 "%s: Unknown error encountered while attempting to "
769 "read coreboot parameter %s\n", prog_name, e->name);
770 return 1;
773 /* read the value from CMOS */
774 set_iopl(3);
775 value = cmos_read(e);
776 set_iopl(0);
778 /* display the value */
779 switch (e->config) {
780 case CMOS_ENTRY_ENUM:
781 if ((p = find_cmos_enum(e->config_id, value)) == NULL) {
782 if (show_name)
783 printf("# Bad value -> %s = 0x%llx\n", e->name,
784 value);
785 else
786 printf("Bad value -> 0x%llx\n", value);
787 } else {
788 if (show_name)
789 printf("%s = %s\n", e->name, p->text);
790 else
791 printf("%s\n", p->text);
794 break;
796 case CMOS_ENTRY_HEX:
797 if (show_name)
798 printf("%s = 0x%llx\n", e->name, value);
799 else
800 printf("0x%llx\n", value);
802 break;
804 case CMOS_ENTRY_STRING:
805 w = (char *)(unsigned long)value;
806 while (*w) {
807 if(!isprint((int)(unsigned char)*w)) {
808 if (show_name)
809 printf("# Bad value -> %s\n", e->name);
810 else
811 printf("Bad value\n");
812 break;
814 w++;
817 if (!*w) {
819 if (show_name)
820 printf("%s = %s\n", e->name,
821 (char *)(unsigned long)value);
822 else
823 printf("%s\n", (char *)(unsigned long)value);
826 free((void *)(unsigned long)value);
828 break;
830 case CMOS_ENTRY_RESERVED:
831 default:
832 BUG();
835 return OK;
838 /****************************************************************************
839 * convert_checksum_value
841 * 'value' is the string representation of a checksum value that the user
842 * wishes to set using the -c option. Convert the string to a 16-bit
843 * unsigned integer and return the result. Exit with an error message if
844 * 'value' is invalid.
845 ****************************************************************************/
846 static uint16_t convert_checksum_value(const char value[])
848 unsigned long n;
849 const char *p;
850 uint16_t result;
851 int negative;
853 for (p = value; isspace((int)(unsigned char)*p); p++) ;
855 negative = (*p == '-');
856 n = strtoul(value, (char **)&p, 0);
858 if (*p) {
859 fprintf(stderr,
860 "%s: Checksum value %s is not a valid integer.\n",
861 prog_name, value);
862 exit(1);
865 if (negative) {
866 fprintf(stderr,
867 "%s: Checksum must be an unsigned integer.\n",
868 prog_name);
869 exit(1);
872 result = (uint16_t) n;
874 if (result != n) {
875 fprintf(stderr,
876 "%s: Checksum value must fit within 16 bits.\n",
877 prog_name);
878 exit(1);
881 return result;