00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include "common.h"
00032 #include "opts.h"
00033 #include "lbtable.h"
00034 #include "layout.h"
00035 #include "layout_file.h"
00036 #include "input_file.h"
00037 #include "cmos_ops.h"
00038 #include "cmos_lowlevel.h"
00039 #include "reg_expr.h"
00040 #include "hexdump.h"
00041
00042 typedef void (*op_fn_t) (void);
00043
00044 static void op_show_version (void);
00045 static void op_show_usage (void);
00046 static void op_lbtable_show_info (void);
00047 static void op_lbtable_dump (void);
00048 static void op_show_param_values (void);
00049 static void op_cmos_show_one_param (void);
00050 static void op_cmos_show_all_params (void);
00051 static void op_cmos_set_one_param (void);
00052 static void op_cmos_set_params_stdin (void);
00053 static void op_cmos_set_params_file (void);
00054 static void op_cmos_checksum (void);
00055 static void op_show_layout (void);
00056 static void op_write_cmos_dump (void);
00057 static void op_read_cmos_dump (void);
00058 static void op_show_cmos_hex_dump (void);
00059 static void op_show_cmos_dumpfile (void);
00060 static int list_one_param (const char name[], int show_name);
00061 static int list_all_params (void);
00062 static void list_param_enums (const char name[]);
00063 static void set_one_param (const char name[], const char value[]);
00064 static void set_params (FILE *f);
00065 static void parse_assignment (char arg[], const char **name,
00066 const char **value);
00067 static int list_cmos_entry (const cmos_entry_t *e, int show_name);
00068 static uint16_t convert_checksum_value (const char value[]);
00069
00070 static const op_fn_t op_fns[] =
00071 { op_show_version,
00072 op_show_usage,
00073 op_lbtable_show_info,
00074 op_lbtable_dump,
00075 op_show_param_values,
00076 op_cmos_show_one_param,
00077 op_cmos_show_all_params,
00078 op_cmos_set_one_param,
00079 op_cmos_set_params_stdin,
00080 op_cmos_set_params_file,
00081 op_cmos_checksum,
00082 op_show_layout,
00083 op_write_cmos_dump,
00084 op_read_cmos_dump,
00085 op_show_cmos_hex_dump,
00086 op_show_cmos_dumpfile
00087 };
00088
00089 static const hexdump_format_t cmos_dump_format =
00090 { 16, 2, "", " | ", " ", " | ", '.', NULL };
00091
00092
00093
00094
00095 int main (int argc, char *argv[])
00096 { cmos_layout_get_fn_t fn;
00097
00098 parse_nvramtool_args(argc, argv);
00099
00100 if (nvramtool_op_modifiers[NVRAMTOOL_MOD_USE_CMOS_LAYOUT_FILE].found)
00101 { set_layout_filename(
00102 nvramtool_op_modifiers[NVRAMTOOL_MOD_USE_CMOS_LAYOUT_FILE].param);
00103 fn = get_layout_from_file;
00104 }
00105 else
00106 fn = get_layout_from_cmos_table;
00107
00108 register_cmos_layout_get_fn(fn);
00109 op_fns[nvramtool_op.op]();
00110 return 0;
00111 }
00112
00113
00114
00115
00116
00117
00118
00119
00120 static void op_show_version (void)
00121 { printf("This is %s version %s.\n", prog_name, prog_version); }
00122
00123
00124
00125
00126
00127
00128
00129
00130 static void op_show_usage (void)
00131 { usage(stdout); }
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141 static void op_lbtable_show_info (void)
00142 { if (nvramtool_op.param == NULL)
00143 list_lbtable_choices();
00144 else
00145 { get_lbtable();
00146 list_lbtable_item(nvramtool_op.param);
00147 }
00148 }
00149
00150
00151
00152
00153
00154
00155
00156
00157 static void op_lbtable_dump (void)
00158 { get_lbtable();
00159 dump_lbtable();
00160 }
00161
00162
00163
00164
00165
00166
00167
00168
00169 static void op_show_param_values (void)
00170 { get_cmos_layout();
00171 list_param_enums(nvramtool_op.param);
00172 }
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182 static void op_cmos_show_one_param (void)
00183 { int result;
00184
00185 get_cmos_layout();
00186 result = list_one_param(nvramtool_op.param,
00187 !nvramtool_op_modifiers[NVRAMTOOL_MOD_SHOW_VALUE_ONLY].found);
00188 cmos_checksum_verify();
00189
00190 if (result)
00191 exit(1);
00192 }
00193
00194
00195
00196
00197
00198
00199
00200
00201 static void op_cmos_show_all_params (void)
00202 { int result;
00203
00204 get_cmos_layout();
00205 result = list_all_params();
00206 cmos_checksum_verify();
00207
00208 if (result)
00209 exit(1);
00210 }
00211
00212
00213
00214
00215
00216
00217
00218
00219 static void op_cmos_set_one_param (void)
00220 { const char *name, *value;
00221
00222 get_cmos_layout();
00223
00224
00225
00226
00227 parse_assignment(nvramtool_op.param, &name, &value);
00228
00229 set_one_param(name, value);
00230 }
00231
00232
00233
00234
00235
00236
00237
00238
00239 static void op_cmos_set_params_stdin (void)
00240 { get_cmos_layout();
00241 set_params(stdin);
00242 }
00243
00244
00245
00246
00247
00248
00249
00250
00251 static void op_cmos_set_params_file (void)
00252 { FILE *f;
00253
00254 if ((f = fopen(nvramtool_op.param, "r")) == NULL)
00255 { fprintf(stderr, "%s: Can not open file %s for reading: %s\n",
00256 prog_name, nvramtool_op.param, strerror(errno));
00257 exit(1);
00258 }
00259
00260 get_cmos_layout();
00261 set_params(f);
00262 fclose(f);
00263 }
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273 static void op_cmos_checksum (void)
00274 { uint16_t checksum;
00275
00276 get_cmos_layout();
00277
00278 if (nvramtool_op.param == NULL)
00279 { set_iopl(3);
00280 checksum = cmos_checksum_read();
00281 set_iopl(0);
00282 printf("0x%x\n", checksum);
00283 }
00284 else
00285 { checksum = convert_checksum_value(nvramtool_op.param);
00286 set_iopl(3);
00287 cmos_checksum_write(checksum);
00288 set_iopl(0);
00289 }
00290 }
00291
00292
00293
00294
00295
00296
00297
00298
00299 static void op_show_layout (void)
00300 { get_cmos_layout();
00301 write_cmos_layout(stdout);
00302 }
00303
00304
00305
00306
00307
00308
00309
00310
00311 static void op_write_cmos_dump (void)
00312 { unsigned char data[CMOS_SIZE];
00313 FILE *f;
00314
00315 if ((f = fopen(nvramtool_op.param, "w")) == NULL)
00316 { fprintf(stderr, "%s: Can not open file %s for writing: %s\n",
00317 prog_name, nvramtool_op.param, strerror(errno));
00318 exit(1);
00319 }
00320
00321 set_iopl(3);
00322 cmos_read_all(data);
00323 set_iopl(0);
00324
00325 if (fwrite(data, 1, CMOS_SIZE, f) != CMOS_SIZE)
00326 { fprintf(stderr, "%s: Error writing CMOS data to file %s: %s\n",
00327 prog_name, nvramtool_op.param, strerror(errno));
00328 exit(1);
00329 }
00330
00331 fclose(f);
00332 }
00333
00334
00335
00336
00337
00338
00339
00340
00341 static void op_read_cmos_dump (void)
00342 { unsigned char data[CMOS_SIZE];
00343 size_t nr_bytes;
00344 FILE *f;
00345
00346 if ((f = fopen(nvramtool_op.param, "r")) == NULL)
00347 { fprintf(stderr, "%s: Can not open file %s for reading: %s\n",
00348 prog_name, nvramtool_op.param, strerror(errno));
00349 exit(1);
00350 }
00351
00352 if ((nr_bytes = fread(data, 1, CMOS_SIZE, f)) != CMOS_SIZE)
00353 { fprintf(stderr, "%s: Error: Only able to read %d bytes of CMOS data "
00354 "from file %s. CMOS data is unchanged.\n", prog_name,
00355 (int) nr_bytes, nvramtool_op.param);
00356 exit(1);
00357 }
00358
00359 fclose(f);
00360 set_iopl(3);
00361 cmos_write_all(data);
00362 set_iopl(0);
00363 }
00364
00365
00366
00367
00368
00369
00370
00371
00372 static void op_show_cmos_hex_dump (void)
00373 { unsigned char data[CMOS_SIZE];
00374
00375 set_iopl(3);
00376 cmos_read_all(data);
00377 set_iopl(0);
00378 hexdump(data, CMOS_SIZE, 0, stdout, &cmos_dump_format);
00379 }
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389 static void op_show_cmos_dumpfile (void)
00390 { unsigned char data[CMOS_SIZE];
00391 size_t nr_bytes;
00392 FILE *f;
00393
00394 if ((f = fopen(nvramtool_op.param, "r")) == NULL)
00395 { fprintf(stderr, "%s: Can not open file %s for reading: %s\n",
00396 prog_name, nvramtool_op.param, strerror(errno));
00397 exit(1);
00398 }
00399
00400 nr_bytes = fread(data, 1, CMOS_SIZE, f);
00401 fclose(f);
00402 hexdump(data, nr_bytes, 0, stdout, &cmos_dump_format);
00403 }
00404
00405
00406
00407
00408
00409
00410
00411
00412 static int list_one_param (const char name[], int show_name)
00413 { const cmos_entry_t *e;
00414
00415 if (is_checksum_name(name) || ((e = find_cmos_entry(name)) == NULL))
00416 { fprintf(stderr, "%s: CMOS parameter %s not found.\n", prog_name, name);
00417 exit(1);
00418 }
00419
00420 if (e->config == CMOS_ENTRY_RESERVED)
00421 { fprintf(stderr, "%s: Parameter %s is reserved.\n", prog_name, name);
00422 exit(1);
00423 }
00424
00425 return (list_cmos_entry(e, show_name) != 0);
00426 }
00427
00428
00429
00430
00431
00432
00433
00434 static int list_all_params (void)
00435 { const cmos_entry_t *e;
00436 int result;
00437
00438 result = OK;
00439
00440 for (e = first_cmos_entry(); e != NULL; e = next_cmos_entry(e))
00441 { if ((e->config == CMOS_ENTRY_RESERVED) || is_checksum_name(e->name))
00442 continue;
00443
00444 if (list_cmos_entry(e, TRUE))
00445 result = 1;
00446 }
00447
00448 return result;
00449 }
00450
00451
00452
00453
00454
00455
00456 static void list_param_enums (const char name[])
00457 { const cmos_entry_t *e;
00458 const cmos_enum_t *p;
00459
00460 if (is_checksum_name(name) || (e = find_cmos_entry(name)) == NULL)
00461 { fprintf(stderr, "%s: CMOS parameter %s not found.\n", prog_name, name);
00462 exit(1);
00463 }
00464
00465 switch (e->config)
00466 { case CMOS_ENTRY_ENUM:
00467 for (p = first_cmos_enum_id(e->config_id);
00468 p != NULL;
00469 p = next_cmos_enum_id(p))
00470 printf("%s\n", p->text);
00471
00472 break;
00473
00474 case CMOS_ENTRY_HEX:
00475 printf("Parameter %s requires a %u-bit unsigned integer.\n", name,
00476 e->length);
00477 break;
00478
00479 case CMOS_ENTRY_STRING:
00480 printf("Parameter %s requires a %u-byte string.\n", name,
00481 e->length / 8);
00482 break;
00483
00484 case CMOS_ENTRY_RESERVED:
00485 printf("Parameter %s is reserved.\n", name);
00486 break;
00487
00488 default:
00489 BUG();
00490 }
00491 }
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503 static void set_one_param (const char name[], const char value[])
00504 { const cmos_entry_t *e;
00505 unsigned long long n;
00506
00507 if (is_checksum_name(name) || (e = find_cmos_entry(name)) == NULL)
00508 { fprintf(stderr, "%s: CMOS parameter %s not found.", prog_name, name);
00509 exit(1);
00510 }
00511
00512 switch (prepare_cmos_write(e, value, &n))
00513 { case OK:
00514 break;
00515
00516 case CMOS_OP_BAD_ENUM_VALUE:
00517 fprintf(stderr, "%s: Bad value for parameter %s.", prog_name, name);
00518 goto fail;
00519
00520 case CMOS_OP_NEGATIVE_INT:
00521 fprintf(stderr,
00522 "%s: This program does not support assignment of negative "
00523 "numbers to coreboot parameters.", prog_name);
00524 goto fail;
00525
00526 case CMOS_OP_INVALID_INT:
00527 fprintf(stderr, "%s: %s is not a valid integer.", prog_name, value);
00528 goto fail;
00529
00530 case CMOS_OP_RESERVED:
00531 fprintf(stderr,
00532 "%s: Can not modify reserved coreboot parameter %s.",
00533 prog_name, name);
00534 goto fail;
00535
00536 case CMOS_OP_VALUE_TOO_WIDE:
00537 fprintf(stderr,
00538 "%s: Can not write value %s to CMOS parameter %s that is "
00539 "only %d bits wide.", prog_name, value, name, e->length);
00540 goto fail;
00541
00542 case CMOS_OP_NO_MATCHING_ENUM:
00543 fprintf(stderr,
00544 "%s: coreboot parameter %s has no matching enums.",
00545 prog_name, name);
00546 goto fail;
00547
00548 case CMOS_AREA_OUT_OF_RANGE:
00549 fprintf(stderr,
00550 "%s: The CMOS area specified by the layout info for "
00551 "coreboot parameter %s is out of range.", prog_name, name);
00552 goto fail;
00553
00554 case CMOS_AREA_OVERLAPS_RTC:
00555 fprintf(stderr,
00556 "%s: The CMOS area specified by the layout info for "
00557 "coreboot parameter %s overlaps the realtime clock area.",
00558 prog_name, name);
00559 goto fail;
00560
00561 case CMOS_AREA_TOO_WIDE:
00562 fprintf(stderr,
00563 "%s: The CMOS area specified by the layout info for "
00564 "coreboot parameter %s is too wide.",
00565 prog_name, name);
00566 goto fail;
00567
00568 default:
00569 fprintf(stderr,
00570 "%s: Unknown error encountered while attempting to modify "
00571 "coreboot parameter %s.", prog_name, name);
00572 goto fail;
00573 }
00574
00575
00576 set_iopl(3);
00577 cmos_write(e, n);
00578 cmos_checksum_write(cmos_checksum_compute());
00579 set_iopl(0);
00580 return;
00581
00582 fail:
00583 fprintf(stderr, " CMOS write not performed.\n");
00584 exit(1);
00585 }
00586
00587
00588
00589
00590
00591
00592 static void set_params (FILE *f)
00593 {
00594
00595
00596
00597 do_cmos_writes(process_input_file(f));
00598 }
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609 static void parse_assignment (char arg[], const char **name,
00610 const char **value)
00611 { static const size_t N_MATCHES = 4;
00612 regmatch_t match[N_MATCHES];
00613 regex_t assignment;
00614
00615 compile_reg_exprs(REG_EXTENDED | REG_NEWLINE, 1, assignment_regex,
00616 &assignment);
00617
00618
00619
00620
00621 if (regexec(&assignment, arg, N_MATCHES, match, 0))
00622 usage(stderr);
00623
00624
00625
00626
00627 arg[match[1].rm_eo] = '\0';
00628 arg[match[2].rm_eo] = '\0';
00629 *name = &arg[match[1].rm_so];
00630 *value = &arg[match[2].rm_so];
00631
00632 free_reg_exprs(1, &assignment);
00633 }
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643 static int list_cmos_entry (const cmos_entry_t *e, int show_name)
00644 { const cmos_enum_t *p;
00645 unsigned long long value;
00646
00647
00648 switch (prepare_cmos_read(e))
00649 { case OK:
00650 break;
00651
00652 case CMOS_OP_RESERVED:
00653 BUG();
00654
00655 case CMOS_AREA_OUT_OF_RANGE:
00656 fprintf(stderr, "%s: Can not read coreboot parameter %s because "
00657 "layout info specifies out of range CMOS area.\n", prog_name,
00658 e->name);
00659 return 1;
00660
00661 case CMOS_AREA_OVERLAPS_RTC:
00662 fprintf(stderr, "%s: Can not read coreboot parameter %s because "
00663 "layout info specifies CMOS area that overlaps realtime "
00664 "clock area.\n", prog_name, e->name);
00665 return 1;
00666
00667 case CMOS_AREA_TOO_WIDE:
00668 fprintf(stderr, "%s: Can not read coreboot parameter %s because "
00669 "layout info specifies CMOS area that is too wide.\n",
00670 prog_name, e->name);
00671 return 1;
00672
00673 default:
00674 fprintf(stderr, "%s: Unknown error encountered while attempting to "
00675 "read coreboot parameter %s\n", prog_name, e->name);
00676 return 1;
00677 }
00678
00679
00680 set_iopl(3);
00681 value = cmos_read(e);
00682 set_iopl(0);
00683
00684
00685 switch (e->config)
00686 { case CMOS_ENTRY_ENUM:
00687 if ((p = find_cmos_enum(e->config_id, value)) == NULL)
00688 { if (show_name)
00689 printf("# Bad value -> %s = 0x%llx\n", e->name, value);
00690 else
00691 printf("Bad value -> 0x%llx\n", value);
00692 }
00693 else
00694 { if (show_name)
00695 printf("%s = %s\n", e->name, p->text);
00696 else
00697 printf("%s\n", p->text);
00698 }
00699
00700 break;
00701
00702 case CMOS_ENTRY_HEX:
00703 if (show_name)
00704 printf("%s = 0x%llx\n", e->name, value);
00705 else
00706 printf("0x%llx\n", value);
00707
00708 break;
00709
00710 case CMOS_ENTRY_STRING:
00711 if (show_name)
00712 printf("%s = %s\n", e->name, (char *)(unsigned long)value);
00713 else
00714 printf("%s\n", (char *)(unsigned long)value);
00715
00716 free((void *)(unsigned long)value);
00717
00718 break;
00719
00720 case CMOS_ENTRY_RESERVED:
00721 default:
00722 BUG();
00723 }
00724
00725 return OK;
00726 }
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736 static uint16_t convert_checksum_value (const char value[])
00737 { unsigned long n;
00738 const char *p;
00739 uint16_t result;
00740 int negative;
00741
00742 for (p = value; isspace(*p); p++);
00743
00744 negative = (*p == '-');
00745 n = strtoul(value, (char **) &p, 0);
00746
00747 if (*p)
00748 { fprintf(stderr, "%s: Checksum value %s is not a valid integer.\n",
00749 prog_name, value);
00750 exit(1);
00751 }
00752
00753 if (negative)
00754 { fprintf(stderr,
00755 "%s: Checksum must be an unsigned integer.\n", prog_name);
00756 exit(1);
00757 }
00758
00759 result = (uint16_t) n;
00760
00761 if (result != n)
00762 { fprintf(stderr,
00763 "%s: Checksum value must fit within 16 bits.\n", prog_name);
00764 exit(1);
00765 }
00766
00767 return result;
00768 }