Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(32)

Side by Side Diff: vpd.c

Issue 6646016: leverage flashrom fast partial read function to speed up VPD read. (Closed) Base URL: ssh://git@gitrw.chromium.org:9222/vpd.git@master
Patch Set: Created 9 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« lib/fmap.c ('K') | « lib/fmap.c ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2010 Google Inc. 2 * Copyright (C) 2010 Google Inc.
3 * 3 *
4 * This program is free software; you can redistribute it and/or 4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License 5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2 6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version. 7 * of the License, or (at your option) any later version.
8 * 8 *
9 * This program is distributed in the hope that it will be useful, 9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
(...skipping 16 matching lines...) Expand all
27 #include "lib/flashrom.h" 27 #include "lib/flashrom.h"
28 #include "lib/fmap.h" 28 #include "lib/fmap.h"
29 #include "lib/lib_vpd.h" 29 #include "lib/lib_vpd.h"
30 #include "lib/lib_smbios.h" 30 #include "lib/lib_smbios.h"
31 #include "lib/vpd.h" 31 #include "lib/vpd.h"
32 #include "lib/vpd_tables.h" 32 #include "lib/vpd_tables.h"
33 33
34 /* The buffer length. Right now the VPD partition size on flash is 128KB. */ 34 /* The buffer length. Right now the VPD partition size on flash is 128KB. */
35 #define BUF_LEN (128 * 1024) 35 #define BUF_LEN (128 * 1024)
36 36
37 static uint8_t flashrom_tmp_file[] = "/tmp/vpd.flashrom.XXXXXX"; 37 /* temp filename for partial read area. */
38 static uint8_t tmp_part_file[] = "/tmp/vpd.flashrom.XXXXXX";
39 /* temp filename for the full flash content (actually only partial content
40 * is available). But for flashrom -w to match flash size, we need to keep this
41 * file from flashromRead() to writeFlashrom(). */
42 static uint8_t tmp_full_file[] = "/tmp/vpd.flashrom.XXXXXX";
dhendrix 2011/03/10 01:33:51 Just a thought (not worth the effort for this CL):
Louis 2011/03/10 08:22:51 mkstemp() is a good idea. I will modify that next
38 43
39 /* 2 containers: 44 /* 2 containers:
40 * file: stores decoded pairs from file. 45 * file: stores decoded pairs from file.
41 * argument: stores parsed pairs from command arguments. 46 * argument: stores parsed pairs from command arguments.
42 */ 47 */
43 struct PairContainer file; 48 struct PairContainer file;
44 struct PairContainer argument; 49 struct PairContainer argument;
45 50
46 /* The current padding length value. 51 /* The current padding length value.
47 * Default: VPD_AS_LONG_AS 52 * Default: VPD_AS_LONG_AS
48 */ 53 */
49 int pad_value_len = VPD_AS_LONG_AS; 54 int pad_value_len = VPD_AS_LONG_AS;
50 55
51 /* The output buffer */ 56 /* The output buffer */
52 unsigned char buf[BUF_LEN]; 57 unsigned char buf[BUF_LEN];
53 int buf_len = 0; 58 int buf_len = 0;
54 int max_buf_len = sizeof(buf); 59 int max_buf_len = sizeof(buf);
55 60
56 /* The EPS base address used to fill the EPS table entry. 61 /* The EPS base address used to fill the EPS table entry.
57 * If the VPD partition can be found in fmap, this points to the starting 62 * If the VPD partition can be found in fmap, this points to the starting
58 * offset of VPD partition. If not found, this is used to be the base address 63 * offset of VPD partition. If not found, this is used to be the base address
59 * to increase SPD and VPD 2.0 offset fields. 64 * to increase SPD and VPD 2.0 offset fields.
60 * 65 *
61 * User can overwrite this by -E argument. 66 * User can overwrite this by -E argument.
62 */ 67 */
63 uint32_t eps_base = GOOGLE_EPS_BASE; 68 uint32_t eps_base = GOOGLE_EPS_BASE;
69 int eps_base_force_specified = 0; /* a bool value to indicate if -E argument
70 * is given. */
64 71
65 /* the fmap name of VPD. */ 72 /* the fmap name of VPD. */
66 uint8_t fmap_vpd_area_name[FMAP_STRLEN] = "RO VPD"; 73 uint8_t fmap_vpd_area_name[FMAP_STRLEN] = "RO_VPD";
67 74
68 /* If found_vpd, replace the VPD partition when saveFile(). 75 /* If found_vpd, replace the VPD partition when saveFile().
69 * If not found, always create new file when saveFlie(). */ 76 * If not found, always create new file when saveFlie(). */
70 int found_vpd = 0; 77 int found_vpd = 0;
71 78
72 /* The VPD partition offset and size in buf[]. The whole partition includes: 79 /* The VPD partition offset and size in buf[]. The whole partition includes:
73 * 80 *
74 * SMBIOS EPS 81 * SMBIOS EPS
75 * SMBIOS tables[] 82 * SMBIOS tables[]
76 * SPD 83 * SPD
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
250 if (-1 == sig_offset) { 257 if (-1 == sig_offset) {
251 /* FMAP signature is not found, assume it is pure VPD partition. */ 258 /* FMAP signature is not found, assume it is pure VPD partition. */
252 vpd_buf = read_buf; 259 vpd_buf = read_buf;
253 eps = (struct vpd_entry *)vpd_buf; 260 eps = (struct vpd_entry *)vpd_buf;
254 261
255 /* In overwrite mode, ignore all existing data. */ 262 /* In overwrite mode, ignore all existing data. */
256 if (overwrite_it) { 263 if (overwrite_it) {
257 retval = 0; 264 retval = 0;
258 goto teardown; 265 goto teardown;
259 } 266 }
267
268 if (!eps_base_force_specified) {
269 /* Since we lost the fmap info in this mode, we try to guess the
270 * eps_base from EPS field. */
271 if (eps->table_address > file_size) {
272 eps_base = eps->table_address - sizeof(*eps);
273 fprintf(stderr, "[INFO] we guess eps_base is 0x%x.\n", eps_base);
274 }
275 }
260 } else { 276 } else {
277 /* FMAP signature is found, try to search the partition name in table. */
261 int i; 278 int i;
262 279
263 fmap = (struct fmap *)&read_buf[sig_offset]; 280 fmap = (struct fmap *)&read_buf[sig_offset];
264 for(i = 0; i < fmap->nareas; i++) { 281 for(i = 0; i < fmap->nareas; i++) {
265 fmapNormalizeAreaName(fmap->areas[i].name); 282 fmapNormalizeAreaName(fmap->areas[i].name);
266 } 283 }
267 284
268 if (FMAP_OK == fmapGetArea(fmap_vpd_area_name, fmap, 285 if (FMAP_OK == fmapGetArea(fmap_vpd_area_name, fmap,
269 &vpd_offset, &vpd_size)) { 286 &vpd_offset, &vpd_size)) {
270 found_vpd = 1; /* Mark found here then saveFile() knows where to 287 found_vpd = 1; /* Mark found here then saveFile() knows where to
(...skipping 14 matching lines...) Expand all
285 goto teardown; 302 goto teardown;
286 } 303 }
287 } 304 }
288 /* Now, vpd_buf points to the VPD partition in buffer. 305 /* Now, vpd_buf points to the VPD partition in buffer.
289 * eps points to the EPS structure, which is usually equal to vpd_buf. */ 306 * eps points to the EPS structure, which is usually equal to vpd_buf. */
290 eps_offset = (uint8_t*)eps - vpd_buf; 307 eps_offset = (uint8_t*)eps - vpd_buf;
291 308
292 /* jump if the VPD partition is not recognized. */ 309 /* jump if the VPD partition is not recognized. */
293 if (memcmp(VPD_ENTRY_MAGIC, eps, sizeof(VPD_ENTRY_MAGIC) - 1)) { 310 if (memcmp(VPD_ENTRY_MAGIC, eps, sizeof(VPD_ENTRY_MAGIC) - 1)) {
294 /* But OKAY if the VPD partition is all-FF, which is un-used. */ 311 /* But OKAY if the VPD partition is all-FF, which is un-used. */
295 if (memcmp("\xff\xff\xff\xff", eps, sizeof(VPD_ENTRY_MAGIC) - 1)) { 312 if (!memcmp("\xff\xff\xff\xff", eps, sizeof(VPD_ENTRY_MAGIC) - 1)) {
313 fprintf(stderr, "[WARN] VPD partition not formatted. Ignored.\n");
314 retval = 0;
315 goto teardown;
316 } else {
dhendrix 2011/03/10 01:33:51 nice!
Louis 2011/03/10 08:22:51 Done.
296 fprintf(stderr, "SMBIOS signature is not matched.\n"); 317 fprintf(stderr, "SMBIOS signature is not matched.\n");
297 fprintf(stderr, "You may use -O to overwrite the data.\n"); 318 fprintf(stderr, "You may use -O to overwrite the data.\n");
298 retval = 1; 319 retval = 1;
299 goto teardown; 320 goto teardown;
300 } 321 }
301 /* TODO(yjlou): need more EPS sanity checks here. */ 322 /* TODO(yjlou): need more EPS sanity checks here. */
302 } 323 }
303 /* EPS is done above. Parse structure tables below. */ 324 /* EPS is done above. Parse structure tables below. */
304 /* Get the first type 241 blob, at the tail of EPS. */ 325 /* Get the first type 241 blob, at the tail of EPS. */
305 header = (struct vpd_header*)(((uint8_t*)eps) + eps->entry_length); 326 header = (struct vpd_header*)(((uint8_t*)eps) + eps->entry_length);
306 data = (struct vpd_table_binary_blob_pointer *) 327 data = (struct vpd_table_binary_blob_pointer *)
307 ((uint8_t *)header + sizeof(*header)); 328 ((uint8_t *)header + sizeof(*header));
308 329
309 /* TODO(yjlou): Re-factor the parsing code to support more SMBIOS entries. 330 /* TODO(yjlou): Re-factor the parsing code to support more SMBIOS entries.
310 * The current code only supports 2 combinations: 331 * The current code only supports 2 combinations:
311 * 1. Type 241 (SPD) + Type 241 (VPD 2.0) + Type 127 332 * 1. Type 241 (SPD) + Type 241 (VPD 2.0) + Type 127
312 * 2. Type 241 (VPD 2.0) + Type 127 333 * 2. Type 241 (VPD 2.0) + Type 127
313 */ 334 */
314 335
315 /* Now header points to the first SMBIOS entry, and data points to the 336 /* Now header points to the first SMBIOS entry, and data points to the
316 * first BBP entry. The first entry could be SPD data. We don't care. */ 337 * first BBP entry. The first entry could be SPD data. We don't care. */
317 if (header->handle != expected_handle) { 338 if (header->handle != expected_handle) {
318 fprintf(stderr, "The first handle value must be 0, but is %d.\n", 339 fprintf(stderr, "[ERROR] The first handle value must be 0, but is %d.\n"
340 " Use -O option to re-format.\n",
319 header->handle); 341 header->handle);
320 retval = 1; 342 retval = 1;
321 goto teardown; 343 goto teardown;
322 } 344 }
323 if (header->type != VPD_TYPE_BINARY_BLOB_POINTER) { 345 if (header->type != VPD_TYPE_BINARY_BLOB_POINTER) {
324 fprintf(stderr, "Expect first entry is type Binary Blob Pointer (241)," 346 fprintf(stderr, "Expect first entry is type Binary Blob Pointer (241),"
325 " but actually is %d\n", header->type); 347 " but actually is %d\n", header->type);
326 fprintf(stderr, "You may use -O to overwrite the data.\n"); 348 fprintf(stderr, "You may use -O to overwrite the data.\n");
327 retval = 1; 349 retval = 1;
328 goto teardown; 350 goto teardown;
(...skipping 26 matching lines...) Expand all
355 retval = 1; 377 retval = 1;
356 goto teardown; 378 goto teardown;
357 } 379 }
358 header = (struct vpd_header*)((uint8_t*)header + table_len); 380 header = (struct vpd_header*)((uint8_t*)header + table_len);
359 data = (struct vpd_table_binary_blob_pointer *) 381 data = (struct vpd_table_binary_blob_pointer *)
360 ((uint8_t *)header + sizeof(*header)); 382 ((uint8_t *)header + sizeof(*header));
361 } 383 }
362 384
363 /* The 2nd could be VPD 2.0 data or End Of Table. */ 385 /* The 2nd could be VPD 2.0 data or End Of Table. */
364 if (header->handle != expected_handle) { 386 if (header->handle != expected_handle) {
365 fprintf(stderr, "The second handle value must be 1, but is %d.\n", 387 fprintf(stderr, "[ERROR] The second handle value must be 1, but is %d.\n"
388 " Use -O option to re-format.\n",
366 header->handle); 389 header->handle);
367 retval = 1; 390 retval = 1;
368 goto teardown; 391 goto teardown;
369 } 392 }
370 uuid_parse(GOOGLE_VPD_2_0_UUID, vpd_2_0_uuid); 393 uuid_parse(GOOGLE_VPD_2_0_UUID, vpd_2_0_uuid);
371 if (header->type == VPD_TYPE_BINARY_BLOB_POINTER && 394 if (header->type == VPD_TYPE_BINARY_BLOB_POINTER &&
372 !memcmp(data->uuid, vpd_2_0_uuid, sizeof(data->uuid))) { 395 !memcmp(data->uuid, vpd_2_0_uuid, sizeof(data->uuid))) {
373 ++expected_handle; 396 ++expected_handle;
374 397
375 /* iterate all pairs */ 398 /* iterate all pairs */
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
483 fprintf(stderr, "fwrite(VPD 2.0) error (%s)\n", strerror(errno)); 506 fprintf(stderr, "fwrite(VPD 2.0) error (%s)\n", strerror(errno));
484 retval = 1; 507 retval = 1;
485 goto teardown; 508 goto teardown;
486 } 509 }
487 fclose(fp); 510 fclose(fp);
488 511
489 teardown: 512 teardown:
490 return retval; 513 return retval;
491 } 514 }
492 515
516 int myMkTemp(uint8_t *tmp_file) {
517 int fd;
518 fd = mkstemp(tmp_file);
519 if (fd < 0) {
520 fprintf(stderr, "mkstemp(%s) failed\n", tmp_file);
521 }
522 return fd;
523 }
524
525 int generateTempFilenames(void) {
526 if (myMkTemp(tmp_part_file) < 0) return -1;
527 if (myMkTemp(tmp_full_file) < 0) return -1;
528 return 0;
529 }
493 530
494 static void usage(const char *progname) { 531 static void usage(const char *progname) {
495 printf("Chrome OS VPD 2.0 utility --\n"); 532 printf("Chrome OS VPD 2.0 utility --\n");
496 #ifdef VPD_VERSION 533 #ifdef VPD_VERSION
497 printf("%s\n", VPD_VERSION); 534 printf("%s\n", VPD_VERSION);
498 #endif 535 #endif
499 printf("\n"); 536 printf("\n");
500 printf("Usage: %s [OPTION] ...\n", progname); 537 printf("Usage: %s [OPTION] ...\n", progname);
501 printf(" OPTIONs include:\n"); 538 printf(" OPTIONs include:\n");
502 printf(" -h This help page and version.\n"); 539 printf(" -h This help page and version.\n");
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
544 goto teardown; 581 goto teardown;
545 break; 582 break;
546 583
547 case 'f': 584 case 'f':
548 filename = strdup(optarg); 585 filename = strdup(optarg);
549 break; 586 break;
550 587
551 case 'E': 588 case 'E':
552 errno = 0; 589 errno = 0;
553 eps_base = strtoul(optarg, (char **) NULL, 0); 590 eps_base = strtoul(optarg, (char **) NULL, 0);
591 eps_base_force_specified = 1;
554 592
555 /* FIXME: this is not a stable way to detect error because 593 /* FIXME: this is not a stable way to detect error because
556 * implementation may (or may not) assign errno. */ 594 * implementation may (or may not) assign errno. */
557 if (!eps_base && errno == EINVAL) { 595 if (!eps_base && errno == EINVAL) {
558 fprintf(stderr, "Not a number for EPS base address: %s\n", optarg); 596 fprintf(stderr, "Not a number for EPS base address: %s\n", optarg);
559 retval = 1; 597 retval = 1;
560 goto teardown; 598 goto teardown;
561 } 599 }
562 break; 600 break;
563 601
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
598 break; 636 break;
599 637
600 default: 638 default:
601 fprintf(stderr, "Invalid option, use --help for usage.\n"); 639 fprintf(stderr, "Invalid option, use --help for usage.\n");
602 retval = 1; 640 retval = 1;
603 goto teardown; 641 goto teardown;
604 break; 642 break;
605 } 643 }
606 } 644 }
607 645
608 fd = mkstemp(flashrom_tmp_file); 646 if (optind < argc) {
609 if (fd < 0) { 647 fprintf(stderr, "[ERROR] unexpected argument: %s\n\n", argv[optind]);
610 fprintf(stderr, "mkstemp(%s) failed\n", flashrom_tmp_file); 648 usage(argv[0]);
611 retval = 1; 649 retval = 1;
612 goto teardown; 650 goto teardown;
613 } 651 }
652
653 if (generateTempFilenames() < 0) {
654 retval = 1;
655 goto teardown;
656 }
614 657
615 /* to avoid malicious attack, we replace suspicious chars. */ 658 /* to avoid malicious attack, we replace suspicious chars. */
616 fmapNormalizeAreaName(fmap_vpd_area_name); 659 fmapNormalizeAreaName(fmap_vpd_area_name);
617 660
618 /* if no filename is specified, call flashrom to read from flash. */ 661 /* if no filename is specified, call flashrom to read from flash. */
619 if (!filename) { 662 if (!filename) {
620 if (FLASHROM_OK != flashromRead(flashrom_tmp_file)) { 663 if (FLASHROM_OK != flashromRead(tmp_part_file, tmp_full_file,
664 fmap_vpd_area_name)) {
621 fprintf(stderr, "flashromRead() error!\n"); 665 fprintf(stderr, "flashromRead() error!\n");
622 retval = 1; 666 retval = 1;
623 goto teardown; 667 goto teardown;
624 } 668 }
625 write_back_to_flash = 1; 669 write_back_to_flash = 1;
626 filename = strdup(flashrom_tmp_file); 670 filename = strdup(tmp_part_file);
627 } 671 }
628 672
629 if (retval = loadFile(filename, &file, overwrite_it)) { 673 if (retval = loadFile(filename, &file, overwrite_it)) {
630 fprintf(stderr, "loadFile('%s') error.\n", filename); 674 fprintf(stderr, "loadFile('%s') error.\n", filename);
631 goto teardown; 675 goto teardown;
632 } 676 }
633 677
634 mergeContainer(&file, &argument); 678 mergeContainer(&file, &argument);
635 679
636 if (list_it) { 680 if (list_it) {
(...skipping 11 matching lines...) Expand all
648 printf("%s", list_buf); 692 printf("%s", list_buf);
649 } 693 }
650 694
651 if (modified) { 695 if (modified) {
652 if (retval = saveFile(&file, filename)) { 696 if (retval = saveFile(&file, filename)) {
653 fprintf(stderr, "saveFile('%s') error.\n", filename); 697 fprintf(stderr, "saveFile('%s') error.\n", filename);
654 goto teardown; 698 goto teardown;
655 } 699 }
656 700
657 if (write_back_to_flash) { 701 if (write_back_to_flash) {
658 if (FLASHROM_OK != flashromPartialWrite(filename, vpd_offset, vpd_size)) { 702 if (FLASHROM_OK != flashromPartialWrite(filename, tmp_full_file,
703 fmap_vpd_area_name)) {
659 fprintf(stderr, "flashromPartialWrite() error.\n"); 704 fprintf(stderr, "flashromPartialWrite() error.\n");
660 retval = 1; 705 retval = 1;
661 goto teardown; 706 goto teardown;
662 } 707 }
663 } 708 }
664 } 709 }
665 710
666 teardown: 711 teardown:
667 if (spd_data) free(spd_data); 712 if (spd_data) free(spd_data);
668 if (filename) free(filename); 713 if (filename) free(filename);
669 destroyContainer(&file); 714 destroyContainer(&file);
670 destroyContainer(&argument); 715 destroyContainer(&argument);
671 716
672 return retval; 717 return retval;
673 } 718 }
OLDNEW
« lib/fmap.c ('K') | « lib/fmap.c ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698