blob: 183247713998232aff660ce429eea7bc0a9d4ff2 [file] [log] [blame]
Stefan Reinauer6540ae52007-07-12 16:35:42 +00001/*****************************************************************************\
Uwe Hermann6e565942008-03-01 19:06:32 +00002 * nvramtool.c
Stefan Reinauer6540ae52007-07-12 16:35:42 +00003 *****************************************************************************
4 * Copyright (C) 2002-2005 The Regents of the University of California.
5 * Produced at the Lawrence Livermore National Laboratory.
6 * Written by Dave Peterson <dsp@llnl.gov> <dave_peterson@pobox.com>.
7 * UCRL-CODE-2003-012
8 * All rights reserved.
9 *
Uwe Hermann6e565942008-03-01 19:06:32 +000010 * This file is part of nvramtool, a utility for reading/writing coreboot
Stefan Reinauerf527e702008-01-18 15:33:49 +000011 * parameters and displaying information from the coreboot table.
Uwe Hermann6e565942008-03-01 19:06:32 +000012 * For details, see http://coreboot.org/nvramtool.
Stefan Reinauer6540ae52007-07-12 16:35:42 +000013 *
14 * Please also read the file DISCLAIMER which is included in this software
15 * distribution.
16 *
17 * This program is free software; you can redistribute it and/or modify it
18 * under the terms of the GNU General Public License (as published by the
19 * Free Software Foundation) version 2, dated June 1991.
20 *
21 * This program is distributed in the hope that it will be useful, but
22 * WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY OF
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the terms and
24 * conditions of the GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License along
27 * with this program; if not, write to the Free Software Foundation, Inc.,
28 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
29\*****************************************************************************/
30
31#include "common.h"
32#include "opts.h"
33#include "lbtable.h"
34#include "layout.h"
35#include "layout_file.h"
36#include "input_file.h"
37#include "cmos_ops.h"
38#include "cmos_lowlevel.h"
39#include "reg_expr.h"
40#include "hexdump.h"
41
42typedef void (*op_fn_t) (void);
43
44static void op_show_version (void);
45static void op_show_usage (void);
46static void op_lbtable_show_info (void);
47static void op_lbtable_dump (void);
48static void op_show_param_values (void);
49static void op_cmos_show_one_param (void);
50static void op_cmos_show_all_params (void);
51static void op_cmos_set_one_param (void);
52static void op_cmos_set_params_stdin (void);
53static void op_cmos_set_params_file (void);
54static void op_cmos_checksum (void);
55static void op_show_layout (void);
56static void op_write_cmos_dump (void);
57static void op_read_cmos_dump (void);
58static void op_show_cmos_hex_dump (void);
59static void op_show_cmos_dumpfile (void);
60static int list_one_param (const char name[], int show_name);
61static int list_all_params (void);
62static void list_param_enums (const char name[]);
63static void set_one_param (const char name[], const char value[]);
64static void set_params (FILE *f);
65static void parse_assignment (char arg[], const char **name,
66 const char **value);
67static int list_cmos_entry (const cmos_entry_t *e, int show_name);
68static uint16_t convert_checksum_value (const char value[]);
69
70static const op_fn_t op_fns[] =
71 { op_show_version,
72 op_show_usage,
73 op_lbtable_show_info,
74 op_lbtable_dump,
75 op_show_param_values,
76 op_cmos_show_one_param,
77 op_cmos_show_all_params,
78 op_cmos_set_one_param,
79 op_cmos_set_params_stdin,
80 op_cmos_set_params_file,
81 op_cmos_checksum,
82 op_show_layout,
83 op_write_cmos_dump,
84 op_read_cmos_dump,
85 op_show_cmos_hex_dump,
86 op_show_cmos_dumpfile
87 };
88
89static const hexdump_format_t cmos_dump_format =
90 { 16, 2, "", " | ", " ", " | ", '.', NULL };
91
92/****************************************************************************
93 * main
94 ****************************************************************************/
95int main (int argc, char *argv[])
96 { cmos_layout_get_fn_t fn;
97
Uwe Hermann6e565942008-03-01 19:06:32 +000098 parse_nvramtool_args(argc, argv);
Stefan Reinauer6540ae52007-07-12 16:35:42 +000099
Uwe Hermann6e565942008-03-01 19:06:32 +0000100 if (nvramtool_op_modifiers[NVRAMTOOL_MOD_USE_CMOS_LAYOUT_FILE].found)
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000101 { set_layout_filename(
Uwe Hermann6e565942008-03-01 19:06:32 +0000102 nvramtool_op_modifiers[NVRAMTOOL_MOD_USE_CMOS_LAYOUT_FILE].param);
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000103 fn = get_layout_from_file;
104 }
105 else
106 fn = get_layout_from_cmos_table;
107
108 register_cmos_layout_get_fn(fn);
Uwe Hermann6e565942008-03-01 19:06:32 +0000109 op_fns[nvramtool_op.op]();
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000110 return 0;
111 }
112
113/****************************************************************************
114 * op_show_version
115 *
116 * -v
117 *
118 * Show version information for this program.
119 ****************************************************************************/
120static void op_show_version (void)
121 { printf("This is %s version %s.\n", prog_name, prog_version); }
122
123/****************************************************************************
124 * op_show_usage
125 *
126 * -h
127 *
128 * Show a usage message for this program.
129 ****************************************************************************/
130static void op_show_usage (void)
131 { usage(stdout); }
132
133/****************************************************************************
134 * op_lbtable_show_info
135 *
136 * -l [ARG]
137 *
Stefan Reinauerf527e702008-01-18 15:33:49 +0000138 * If ARG is present, show coreboot table information specified by ARG.
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000139 * Else show all possible values for ARG.
140 ****************************************************************************/
141static void op_lbtable_show_info (void)
Uwe Hermann6e565942008-03-01 19:06:32 +0000142 { if (nvramtool_op.param == NULL)
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000143 list_lbtable_choices();
144 else
145 { get_lbtable();
Uwe Hermann6e565942008-03-01 19:06:32 +0000146 list_lbtable_item(nvramtool_op.param);
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000147 }
148 }
149
150/****************************************************************************
151 * op_lbtable_dump
152 *
153 * -d
154 *
Stefan Reinauerf527e702008-01-18 15:33:49 +0000155 * Do low-level dump of coreboot table.
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000156 ****************************************************************************/
157static void op_lbtable_dump (void)
158 { get_lbtable();
159 dump_lbtable();
160 }
161
162/****************************************************************************
163 * op_show_param_values
164 *
165 * -e NAME option
166 *
167 * Show all possible values for parameter NAME.
168 ****************************************************************************/
169static void op_show_param_values (void)
170 { get_cmos_layout();
Uwe Hermann6e565942008-03-01 19:06:32 +0000171 list_param_enums(nvramtool_op.param);
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000172 }
173
174/****************************************************************************
175 * op_cmos_show_one_param
176 *
177 * [-n] -r NAME
178 *
179 * Show parameter NAME. If -n is specified, show value only. Else show name
180 * and value.
181 ****************************************************************************/
182static void op_cmos_show_one_param (void)
183 { int result;
184
185 get_cmos_layout();
Uwe Hermann6e565942008-03-01 19:06:32 +0000186 result = list_one_param(nvramtool_op.param,
187 !nvramtool_op_modifiers[NVRAMTOOL_MOD_SHOW_VALUE_ONLY].found);
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000188 cmos_checksum_verify();
189
190 if (result)
191 exit(1);
192 }
193
194/****************************************************************************
195 * op_cmos_show_all_params
196 *
197 * -a
198 *
199 * Show names and values for all parameters.
200 ****************************************************************************/
201static void op_cmos_show_all_params (void)
202 { int result;
203
204 get_cmos_layout();
205 result = list_all_params();
206 cmos_checksum_verify();
207
208 if (result)
209 exit(1);
210 }
211
212/****************************************************************************
213 * op_cmos_set_one_param
214 *
215 * -w NAME=VALUE
216 *
217 * Set parameter NAME to VALUE.
218 ****************************************************************************/
219static void op_cmos_set_one_param (void)
220 { const char *name, *value;
221
222 get_cmos_layout();
223
224 /* Separate 'NAME=VALUE' syntax into two strings representing NAME and
225 * VALUE.
226 */
Uwe Hermann6e565942008-03-01 19:06:32 +0000227 parse_assignment(nvramtool_op.param, &name, &value);
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000228
229 set_one_param(name, value);
230 }
231
232/****************************************************************************
233 * op_cmos_set_params_stdin
234 *
235 * -i
236 *
237 * Set parameters according to standard input.
238 ****************************************************************************/
239static void op_cmos_set_params_stdin (void)
240 { get_cmos_layout();
241 set_params(stdin);
242 }
243
244/****************************************************************************
245 * op_cmos_set_params_file
246 *
247 * -p INPUT_FILE
248 *
249 * Set parameters according to INPUT_FILE.
250 ****************************************************************************/
251static void op_cmos_set_params_file (void)
252 { FILE *f;
253
Uwe Hermann6e565942008-03-01 19:06:32 +0000254 if ((f = fopen(nvramtool_op.param, "r")) == NULL)
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000255 { fprintf(stderr, "%s: Can not open file %s for reading: %s\n",
Uwe Hermann6e565942008-03-01 19:06:32 +0000256 prog_name, nvramtool_op.param, strerror(errno));
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000257 exit(1);
258 }
259
260 get_cmos_layout();
261 set_params(f);
262 fclose(f);
263 }
264
265/****************************************************************************
266 * op_cmos_checksum
267 *
268 * -c [VALUE]
269 *
Stefan Reinauerf527e702008-01-18 15:33:49 +0000270 * If VALUE is present, set coreboot CMOS checksum to VALUE. Else show
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000271 * checksum value.
272 ****************************************************************************/
273static void op_cmos_checksum (void)
274 { uint16_t checksum;
275
276 get_cmos_layout();
277
Uwe Hermann6e565942008-03-01 19:06:32 +0000278 if (nvramtool_op.param == NULL)
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000279 { set_iopl(3);
280 checksum = cmos_checksum_read();
281 set_iopl(0);
282 printf("0x%x\n", checksum);
283 }
284 else
Uwe Hermann6e565942008-03-01 19:06:32 +0000285 { checksum = convert_checksum_value(nvramtool_op.param);
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000286 set_iopl(3);
287 cmos_checksum_write(checksum);
288 set_iopl(0);
289 }
290 }
291
292/****************************************************************************
293 * op_show_layout
294 *
295 * -Y
296 *
297 * Write CMOS layout information to standard output.
298 ****************************************************************************/
299static void op_show_layout (void)
300 { get_cmos_layout();
301 write_cmos_layout(stdout);
302 }
303
304/****************************************************************************
305 * op_write_cmos_dump
306 *
307 * -b OUTPUT_FILE
308 *
309 * Write the contents of CMOS memory to a binary file.
310 ****************************************************************************/
311static void op_write_cmos_dump (void)
312 { unsigned char data[CMOS_SIZE];
313 FILE *f;
314
Uwe Hermann6e565942008-03-01 19:06:32 +0000315 if ((f = fopen(nvramtool_op.param, "w")) == NULL)
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000316 { fprintf(stderr, "%s: Can not open file %s for writing: %s\n",
Uwe Hermann6e565942008-03-01 19:06:32 +0000317 prog_name, nvramtool_op.param, strerror(errno));
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000318 exit(1);
319 }
320
321 set_iopl(3);
322 cmos_read_all(data);
323 set_iopl(0);
324
325 if (fwrite(data, 1, CMOS_SIZE, f) != CMOS_SIZE)
326 { fprintf(stderr, "%s: Error writing CMOS data to file %s: %s\n",
Uwe Hermann6e565942008-03-01 19:06:32 +0000327 prog_name, nvramtool_op.param, strerror(errno));
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000328 exit(1);
329 }
330
331 fclose(f);
332 }
333
334/****************************************************************************
335 * op_read_cmos_dump
336 *
337 * -B INPUT_FILE
338 *
339 * Read binary data from a file and write the data to CMOS memory.
340 ****************************************************************************/
341static void op_read_cmos_dump (void)
342 { unsigned char data[CMOS_SIZE];
343 size_t nr_bytes;
344 FILE *f;
345
Uwe Hermann6e565942008-03-01 19:06:32 +0000346 if ((f = fopen(nvramtool_op.param, "r")) == NULL)
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000347 { fprintf(stderr, "%s: Can not open file %s for reading: %s\n",
Uwe Hermann6e565942008-03-01 19:06:32 +0000348 prog_name, nvramtool_op.param, strerror(errno));
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000349 exit(1);
350 }
351
352 if ((nr_bytes = fread(data, 1, CMOS_SIZE, f)) != CMOS_SIZE)
353 { fprintf(stderr, "%s: Error: Only able to read %d bytes of CMOS data "
354 "from file %s. CMOS data is unchanged.\n", prog_name,
Uwe Hermann6e565942008-03-01 19:06:32 +0000355 (int) nr_bytes, nvramtool_op.param);
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000356 exit(1);
357 }
358
359 fclose(f);
360 set_iopl(3);
361 cmos_write_all(data);
362 set_iopl(0);
363 }
364
365/****************************************************************************
366 * op_show_cmos_hex_dump
367 *
368 * -x
369 *
370 * Write a hex dump of CMOS memory to standard output.
371 ****************************************************************************/
372static void op_show_cmos_hex_dump (void)
373 { unsigned char data[CMOS_SIZE];
374
375 set_iopl(3);
376 cmos_read_all(data);
377 set_iopl(0);
378 hexdump(data, CMOS_SIZE, 0, stdout, &cmos_dump_format);
379 }
380
381/****************************************************************************
382 * op_show_cmos_dumpfile
383 *
384 * -X DUMP_FILE
385 *
386 * Read binary data from a file (presumably a CMOS dump file) and display a
387 * hex dump of the CMOS data from the file.
388 ****************************************************************************/
389static void op_show_cmos_dumpfile (void)
390 { unsigned char data[CMOS_SIZE];
391 size_t nr_bytes;
392 FILE *f;
393
Uwe Hermann6e565942008-03-01 19:06:32 +0000394 if ((f = fopen(nvramtool_op.param, "r")) == NULL)
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000395 { fprintf(stderr, "%s: Can not open file %s for reading: %s\n",
Uwe Hermann6e565942008-03-01 19:06:32 +0000396 prog_name, nvramtool_op.param, strerror(errno));
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000397 exit(1);
398 }
399
400 nr_bytes = fread(data, 1, CMOS_SIZE, f);
401 fclose(f);
402 hexdump(data, nr_bytes, 0, stdout, &cmos_dump_format);
403 }
404
405/****************************************************************************
406 * list_one_param
407 *
408 * Attempt to list one CMOS parameter given by 'name'. 'show_name' is a
409 * boolean value indicating whether the parameter name should be displayed
410 * along with its value. Return 1 if error was encountered. Else return OK.
411 ****************************************************************************/
412static int list_one_param (const char name[], int show_name)
413 { const cmos_entry_t *e;
414
415 if (is_checksum_name(name) || ((e = find_cmos_entry(name)) == NULL))
416 { fprintf(stderr, "%s: CMOS parameter %s not found.\n", prog_name, name);
417 exit(1);
418 }
419
420 if (e->config == CMOS_ENTRY_RESERVED)
421 { fprintf(stderr, "%s: Parameter %s is reserved.\n", prog_name, name);
422 exit(1);
423 }
424
425 return (list_cmos_entry(e, show_name) != 0);
426 }
427
428/****************************************************************************
429 * list_all_params
430 *
431 * Attempt to list all CMOS parameters. Return 1 if error was encountered.
432 * Else return OK.
433 ****************************************************************************/
434static int list_all_params (void)
435 { const cmos_entry_t *e;
436 int result;
437
438 result = OK;
439
440 for (e = first_cmos_entry(); e != NULL; e = next_cmos_entry(e))
441 { if ((e->config == CMOS_ENTRY_RESERVED) || is_checksum_name(e->name))
442 continue;
443
444 if (list_cmos_entry(e, TRUE))
445 result = 1;
446 }
447
448 return result;
449 }
450
451/****************************************************************************
452 * list_param_enums
453 *
454 * List all possible values for CMOS parameter given by 'name'.
455 ****************************************************************************/
456static void list_param_enums (const char name[])
457 { const cmos_entry_t *e;
458 const cmos_enum_t *p;
459
460 if (is_checksum_name(name) || (e = find_cmos_entry(name)) == NULL)
461 { fprintf(stderr, "%s: CMOS parameter %s not found.\n", prog_name, name);
462 exit(1);
463 }
464
465 switch (e->config)
466 { case CMOS_ENTRY_ENUM:
467 for (p = first_cmos_enum_id(e->config_id);
468 p != NULL;
469 p = next_cmos_enum_id(p))
470 printf("%s\n", p->text);
471
472 break;
473
474 case CMOS_ENTRY_HEX:
475 printf("Parameter %s requires a %u-bit unsigned integer.\n", name,
476 e->length);
477 break;
478
Stefan Reinauera67aab72008-09-27 10:08:28 +0000479 case CMOS_ENTRY_STRING:
480 printf("Parameter %s requires a %u-byte string.\n", name,
481 e->length / 8);
482 break;
483
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000484 case CMOS_ENTRY_RESERVED:
485 printf("Parameter %s is reserved.\n", name);
486 break;
487
488 default:
489 BUG();
490 }
491 }
492
493/****************************************************************************
494 * set_one_param
495 *
496 * Set the CMOS parameter given by 'name' to 'value'. The 'name' parameter
497 * is case-sensitive. If we are setting an enum parameter, then 'value' is
498 * interpreted as a case-sensitive string that must match the option name
499 * exactly. If we are setting a 'hex' parameter, then 'value' is treated as
500 * a string representation of an unsigned integer that may be specified in
501 * decimal, hex, or octal.
502 ****************************************************************************/
503static void set_one_param (const char name[], const char value[])
504 { const cmos_entry_t *e;
505 unsigned long long n;
506
507 if (is_checksum_name(name) || (e = find_cmos_entry(name)) == NULL)
508 { fprintf(stderr, "%s: CMOS parameter %s not found.", prog_name, name);
509 exit(1);
510 }
511
512 switch (prepare_cmos_write(e, value, &n))
513 { case OK:
514 break;
515
516 case CMOS_OP_BAD_ENUM_VALUE:
517 fprintf(stderr, "%s: Bad value for parameter %s.", prog_name, name);
518 goto fail;
519
520 case CMOS_OP_NEGATIVE_INT:
521 fprintf(stderr,
522 "%s: This program does not support assignment of negative "
Stefan Reinauerf527e702008-01-18 15:33:49 +0000523 "numbers to coreboot parameters.", prog_name);
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000524 goto fail;
525
526 case CMOS_OP_INVALID_INT:
527 fprintf(stderr, "%s: %s is not a valid integer.", prog_name, value);
528 goto fail;
529
530 case CMOS_OP_RESERVED:
531 fprintf(stderr,
Stefan Reinauerf527e702008-01-18 15:33:49 +0000532 "%s: Can not modify reserved coreboot parameter %s.",
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000533 prog_name, name);
534 goto fail;
535
536 case CMOS_OP_VALUE_TOO_WIDE:
537 fprintf(stderr,
538 "%s: Can not write value %s to CMOS parameter %s that is "
539 "only %d bits wide.", prog_name, value, name, e->length);
540 goto fail;
541
542 case CMOS_OP_NO_MATCHING_ENUM:
543 fprintf(stderr,
Stefan Reinauerf527e702008-01-18 15:33:49 +0000544 "%s: coreboot parameter %s has no matching enums.",
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000545 prog_name, name);
546 goto fail;
547
548 case CMOS_AREA_OUT_OF_RANGE:
549 fprintf(stderr,
550 "%s: The CMOS area specified by the layout info for "
Stefan Reinauerf527e702008-01-18 15:33:49 +0000551 "coreboot parameter %s is out of range.", prog_name, name);
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000552 goto fail;
553
554 case CMOS_AREA_OVERLAPS_RTC:
555 fprintf(stderr,
556 "%s: The CMOS area specified by the layout info for "
Stefan Reinauerf527e702008-01-18 15:33:49 +0000557 "coreboot parameter %s overlaps the realtime clock area.",
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000558 prog_name, name);
559 goto fail;
560
561 case CMOS_AREA_TOO_WIDE:
562 fprintf(stderr,
563 "%s: The CMOS area specified by the layout info for "
Stefan Reinauerf527e702008-01-18 15:33:49 +0000564 "coreboot parameter %s is too wide.",
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000565 prog_name, name);
566 goto fail;
567
568 default:
569 fprintf(stderr,
570 "%s: Unknown error encountered while attempting to modify "
Stefan Reinauerf527e702008-01-18 15:33:49 +0000571 "coreboot parameter %s.", prog_name, name);
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000572 goto fail;
573 }
574
575 /* write the value to nonvolatile RAM */
576 set_iopl(3);
Stefan Reinauera67aab72008-09-27 10:08:28 +0000577 cmos_write(e, n);
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000578 cmos_checksum_write(cmos_checksum_compute());
579 set_iopl(0);
580 return;
581
582fail:
583 fprintf(stderr, " CMOS write not performed.\n");
584 exit(1);
585 }
586
587/****************************************************************************
588 * set_params
589 *
Stefan Reinauerf527e702008-01-18 15:33:49 +0000590 * Set coreboot parameters according to the contents of file 'f'.
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000591 ****************************************************************************/
592static void set_params (FILE *f)
593 { /* First process the input file. Then perform writes only if there were
594 * no problems processing the input. Either all values will be written
595 * successfully or no values will be written.
596 */
597 do_cmos_writes(process_input_file(f));
598 }
599
600/****************************************************************************
601 * parse_assignment
602 *
603 * Parse the string 'arg' (which supposedly represents an assignment) into a
604 * NAME and a VALUE. If 'arg' does not conform to the proper assignment
605 * syntax, exit with a usage message. Otherwise, on return, 'arg' is broken
606 * into substrings representing NAME and VALUE, and *name and *value are set
607 * to point to these two substrings.
608 ****************************************************************************/
609static void parse_assignment (char arg[], const char **name,
610 const char **value)
611 { static const size_t N_MATCHES = 4;
612 regmatch_t match[N_MATCHES];
613 regex_t assignment;
614
615 compile_reg_exprs(REG_EXTENDED | REG_NEWLINE, 1, assignment_regex,
616 &assignment);
617
618 /* Does 'arg' conform to proper assignment syntax? If not, exit with a
619 * usage message.
620 */
621 if (regexec(&assignment, arg, N_MATCHES, match, 0))
622 usage(stderr);
623
624 /* Ok, we found a valid assignment. Break it into two strings
625 * representing NAME and VALUE.
626 */
627 arg[match[1].rm_eo] = '\0';
628 arg[match[2].rm_eo] = '\0';
629 *name = &arg[match[1].rm_so];
630 *value = &arg[match[2].rm_so];
631
632 free_reg_exprs(1, &assignment);
633 }
634
635/****************************************************************************
636 * list_cmos_entry
637 *
638 * Attempt to list the CMOS entry represented by 'e'. 'show_name' is a
639 * boolean value indicating whether the parameter name should be displayed
640 * along with its value. On success, return OK. On error, print an error
641 * message and return 1.
642 ****************************************************************************/
643static int list_cmos_entry (const cmos_entry_t *e, int show_name)
644 { const cmos_enum_t *p;
645 unsigned long long value;
646
647 /* sanity check CMOS entry */
648 switch (prepare_cmos_read(e))
649 { case OK:
650 break;
651
652 case CMOS_OP_RESERVED:
653 BUG();
654
655 case CMOS_AREA_OUT_OF_RANGE:
Stefan Reinauerf527e702008-01-18 15:33:49 +0000656 fprintf(stderr, "%s: Can not read coreboot parameter %s because "
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000657 "layout info specifies out of range CMOS area.\n", prog_name,
658 e->name);
659 return 1;
660
661 case CMOS_AREA_OVERLAPS_RTC:
Stefan Reinauerf527e702008-01-18 15:33:49 +0000662 fprintf(stderr, "%s: Can not read coreboot parameter %s because "
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000663 "layout info specifies CMOS area that overlaps realtime "
664 "clock area.\n", prog_name, e->name);
665 return 1;
666
667 case CMOS_AREA_TOO_WIDE:
Stefan Reinauerf527e702008-01-18 15:33:49 +0000668 fprintf(stderr, "%s: Can not read coreboot parameter %s because "
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000669 "layout info specifies CMOS area that is too wide.\n",
670 prog_name, e->name);
671 return 1;
672
673 default:
674 fprintf(stderr, "%s: Unknown error encountered while attempting to "
Stefan Reinauerf527e702008-01-18 15:33:49 +0000675 "read coreboot parameter %s\n", prog_name, e->name);
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000676 return 1;
677 }
678
679 /* read the value from CMOS */
680 set_iopl(3);
Stefan Reinauera67aab72008-09-27 10:08:28 +0000681 value = cmos_read(e);
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000682 set_iopl(0);
683
684 /* display the value */
685 switch (e->config)
686 { case CMOS_ENTRY_ENUM:
687 if ((p = find_cmos_enum(e->config_id, value)) == NULL)
688 { if (show_name)
689 printf("# Bad value -> %s = 0x%llx\n", e->name, value);
690 else
691 printf("Bad value -> 0x%llx\n", value);
692 }
693 else
694 { if (show_name)
695 printf("%s = %s\n", e->name, p->text);
696 else
697 printf("%s\n", p->text);
698 }
699
700 break;
701
702 case CMOS_ENTRY_HEX:
703 if (show_name)
704 printf("%s = 0x%llx\n", e->name, value);
705 else
706 printf("0x%llx\n", value);
707
708 break;
709
Stefan Reinauera67aab72008-09-27 10:08:28 +0000710 case CMOS_ENTRY_STRING:
711 if (show_name)
712 printf("%s = %s\n", e->name, (char *)(unsigned long)value);
713 else
714 printf("%s\n", (char *)(unsigned long)value);
715
716 free((void *)(unsigned long)value);
717
718 break;
719
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000720 case CMOS_ENTRY_RESERVED:
721 default:
722 BUG();
723 }
724
725 return OK;
726 }
727
728/****************************************************************************
729 * convert_checksum_value
730 *
731 * 'value' is the string representation of a checksum value that the user
732 * wishes to set using the -c option. Convert the string to a 16-bit
733 * unsigned integer and return the result. Exit with an error message if
734 * 'value' is invalid.
735 ****************************************************************************/
736static uint16_t convert_checksum_value (const char value[])
737 { unsigned long n;
738 const char *p;
739 uint16_t result;
740 int negative;
741
742 for (p = value; isspace(*p); p++);
743
744 negative = (*p == '-');
745 n = strtoul(value, (char **) &p, 0);
746
747 if (*p)
748 { fprintf(stderr, "%s: Checksum value %s is not a valid integer.\n",
749 prog_name, value);
750 exit(1);
751 }
752
753 if (negative)
754 { fprintf(stderr,
755 "%s: Checksum must be an unsigned integer.\n", prog_name);
756 exit(1);
757 }
758
759 result = (uint16_t) n;
760
761 if (result != n)
762 { fprintf(stderr,
763 "%s: Checksum value must fit within 16 bits.\n", prog_name);
764 exit(1);
765 }
766
767 return result;
768 }