| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 // | 4 // |
| 5 // Utility for manipulating Google Binary Block (GBB) | 5 // Utility for manipulating Google Binary Block (GBB) |
| 6 // | 6 // |
| 7 | 7 |
| 8 #include "gbb_utility.h" | 8 #include "gbb_utility.h" |
| 9 | 9 |
| 10 #include <assert.h> | 10 #include <assert.h> |
| 11 #include <getopt.h> | 11 #include <getopt.h> |
| 12 #include <stdio.h> | 12 #include <stdio.h> |
| 13 #include <stdlib.h> |
| 13 #include <string.h> | 14 #include <string.h> |
| 14 | 15 |
| 15 #include <string> | 16 #include <string> |
| 16 #include <vector> | 17 #include <vector> |
| 17 #include <algorithm> | 18 #include <algorithm> |
| 18 | 19 |
| 19 using std::string; | 20 using std::string; |
| 20 | 21 |
| 21 /////////////////////////////////////////////////////////////////////// | 22 /////////////////////////////////////////////////////////////////////// |
| 22 // Simple File Utilities | 23 // Simple File Utilities |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 86 } | 87 } |
| 87 | 88 |
| 88 void GoogleBinaryBlockUtil::initialize() { | 89 void GoogleBinaryBlockUtil::initialize() { |
| 89 verbose = true; | 90 verbose = true; |
| 90 is_valid_gbb = false; | 91 is_valid_gbb = false; |
| 91 header_offset_ = 0; | 92 header_offset_ = 0; |
| 92 memset(&header_, 0, sizeof(header_)); | 93 memset(&header_, 0, sizeof(header_)); |
| 93 file_content_.clear(); | 94 file_content_.clear(); |
| 94 } | 95 } |
| 95 | 96 |
| 97 bool GoogleBinaryBlockUtil::create_new( |
| 98 const std::vector<uint32_t> &create_param) { |
| 99 uint32_t *prop = &header_.hwid_offset; // must be first entry. |
| 100 uint32_t allocated_size = sizeof(header_); |
| 101 std::vector<uint32_t>::const_iterator i = create_param.begin(); |
| 102 |
| 103 // max properties = available space in header / size of record (offset+size) |
| 104 size_t max_properties = |
| 105 (sizeof(header_) - (reinterpret_cast<uint8_t*>(prop) - |
| 106 reinterpret_cast<uint8_t*>(&header_))) / |
| 107 (sizeof(uint32_t) * 2); |
| 108 |
| 109 if (create_param.size() >= max_properties) { |
| 110 if (verbose) |
| 111 fprintf(stderr, "error: creation parameters cannot exceed %zu entries.\n", |
| 112 max_properties); |
| 113 return false; |
| 114 } |
| 115 |
| 116 initialize(); |
| 117 memcpy(header_.signature, GBB_SIGNATURE, GBB_SIGNATURE_SIZE); |
| 118 header_.major_version = GBB_MAJOR_VER; |
| 119 header_.minor_version = GBB_MINOR_VER; |
| 120 header_.header_size = GBB_HEADER_SIZE; |
| 121 |
| 122 while (i != create_param.end()) { |
| 123 *prop++ = allocated_size; // property offset |
| 124 *prop++ = *i; // property size |
| 125 allocated_size += *i; |
| 126 i++; |
| 127 } |
| 128 |
| 129 file_content_.resize(allocated_size); |
| 130 std::copy(reinterpret_cast<char*>(&header_), |
| 131 reinterpret_cast<char*>(&header_ + 1), |
| 132 file_content_.begin()); |
| 133 is_valid_gbb = true; |
| 134 return true; |
| 135 } |
| 136 |
| 137 |
| 96 bool GoogleBinaryBlockUtil::load_from_file(const char *filename) { | 138 bool GoogleBinaryBlockUtil::load_from_file(const char *filename) { |
| 97 is_valid_gbb = false; | 139 is_valid_gbb = false; |
| 98 | 140 |
| 99 file_content_ = read_nonempty_file(filename); | 141 file_content_ = read_nonempty_file(filename); |
| 100 if (file_content_.empty()) | 142 if (file_content_.empty()) |
| 101 return false; | 143 return false; |
| 102 | 144 |
| 103 switch (search_header_signatures(file_content_, &header_offset_)) { | 145 switch (search_header_signatures(file_content_, &header_offset_)) { |
| 104 case 0: | 146 case 0: |
| 105 if (verbose) | 147 if (verbose) |
| (...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 367 // command line utilities | 409 // command line utilities |
| 368 | 410 |
| 369 #include <map> | 411 #include <map> |
| 370 | 412 |
| 371 using vboot_reference::GoogleBinaryBlockUtil; | 413 using vboot_reference::GoogleBinaryBlockUtil; |
| 372 | 414 |
| 373 // utility function: provide usage of this utility and exit. | 415 // utility function: provide usage of this utility and exit. |
| 374 static void usagehelp_exit(const char *prog_name) { | 416 static void usagehelp_exit(const char *prog_name) { |
| 375 printf( | 417 printf( |
| 376 "Utility to manage Google Binary Block (GBB)\n" | 418 "Utility to manage Google Binary Block (GBB)\n" |
| 377 "Usage: %s [-g|-s] [OPTIONS] bios_file [output_file]\n" | 419 "Usage: %s [-g|-s|-c] [OPTIONS] bios_file [output_file]\n" |
| 378 "\n" | 420 "\n" |
| 379 "GET MODE:\n" | 421 "GET MODE:\n" |
| 380 "-g, --get (default)\tGet (read) from bios_file, " | 422 "-g, --get (default)\tGet (read) from bios_file, " |
| 381 "with following options:\n" | 423 "with following options:\n" |
| 382 " --hwid \tReport hardware id (default).\n" | 424 " --hwid \tReport hardware id (default).\n" |
| 383 " -k, --rootkey=FILE \tFile name to export Root Key.\n" | 425 " -k, --rootkey=FILE \tFile name to export Root Key.\n" |
| 384 " -b, --bmpfv=FILE \tFile name to export Bitmap FV.\n" | 426 " -b, --bmpfv=FILE \tFile name to export Bitmap FV.\n" |
| 385 " --recoverykey=FILE\tFile name to export Recovery Key.\n" | 427 " --recoverykey=FILE\tFile name to export Recovery Key.\n" |
| 386 "\n" | 428 "\n" |
| 387 "SET MODE:\n" | 429 "SET MODE:\n" |
| 388 "-s, --set \tSet (write) to bios_file, " | 430 "-s, --set \tSet (write) to bios_file, " |
| 389 "with following options:\n" | 431 "with following options:\n" |
| 390 " -o, --output=FILE \tNew file name for ouptput.\n" | 432 " -o, --output=FILE \tNew file name for ouptput.\n" |
| 391 " -i, --hwid=HWID \tThe new hardware id to be changed.\n" | 433 " -i, --hwid=HWID \tThe new hardware id to be changed.\n" |
| 392 " -k, --rootkey=FILE \tFile name of new Root Key.\n" | 434 " -k, --rootkey=FILE \tFile name of new Root Key.\n" |
| 393 " -b, --bmpfv=FILE \tFile name of new Bitmap FV.\n" | 435 " -b, --bmpfv=FILE \tFile name of new Bitmap FV.\n" |
| 394 " --recoverykey=FILE\tFile name of new Recovery Key.\n" | 436 " --recoverykey=FILE\tFile name of new Recovery Key.\n" |
| 395 "\n" | 437 "\n" |
| 438 "CREATE MODE:\n" |
| 439 "-c, --create=prop1_size,prop2_size...\n" |
| 440 " \tCreate a GBB blob by given size list.\n" |
| 396 "SAMPLE:\n" | 441 "SAMPLE:\n" |
| 397 " %s -g bios.bin\n" | 442 " %s -g bios.bin\n" |
| 398 " %s --set --hwid='New Model' -k key.bin bios.bin newbios.bin\n" | 443 " %s --set --hwid='New Model' -k key.bin bios.bin newbios.bin\n" |
| 399 , prog_name, prog_name, prog_name); | 444 " %s -c 0x100,0x1000,0x03DE80,0x1000 gbb.blob\n" |
| 445 , prog_name, prog_name, prog_name, prog_name); |
| 400 exit(1); | 446 exit(1); |
| 401 } | 447 } |
| 402 | 448 |
| 403 // utility function: export a property from GBB to given file. | 449 // utility function: export a property from GBB to given file. |
| 404 // if filename was empty, export to console (screen). | 450 // if filename was empty, export to console (screen). |
| 405 // return true on success, otherwise false. | 451 // return true on success, otherwise false. |
| 406 static bool export_property(GoogleBinaryBlockUtil::PROPINDEX idx, | 452 static bool export_property(GoogleBinaryBlockUtil::PROPINDEX idx, |
| 407 const string &filename, | 453 const string &filename, |
| 408 const GoogleBinaryBlockUtil &util) { | 454 const GoogleBinaryBlockUtil &util) { |
| 409 string prop_name = util.get_property_name(idx), | 455 string prop_name = util.get_property_name(idx), |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 454 printf(" - %s changed from '%s' to '%s': %s\n", | 500 printf(" - %s changed from '%s' to '%s': %s\n", |
| 455 prop_name.c_str(), old_value.c_str(), source.c_str(), | 501 prop_name.c_str(), old_value.c_str(), source.c_str(), |
| 456 result ? "success" : "failed"); | 502 result ? "success" : "failed"); |
| 457 if (!result) | 503 if (!result) |
| 458 return false; | 504 return false; |
| 459 } | 505 } |
| 460 | 506 |
| 461 return true; | 507 return true; |
| 462 } | 508 } |
| 463 | 509 |
| 510 static bool parse_creation_param(const string &input_string, |
| 511 std::vector<uint32_t> *output_vector) { |
| 512 const char *input = input_string.c_str(); |
| 513 char *parsed = NULL; |
| 514 uint32_t param; |
| 515 |
| 516 if (input_string.empty()) |
| 517 return false; |
| 518 |
| 519 do { |
| 520 param = (uint32_t)strtol(input, &parsed, 0); |
| 521 if (*parsed && *parsed != ',') |
| 522 return false; |
| 523 output_vector->push_back(param); |
| 524 input = parsed + 1; |
| 525 // printf("(debug) param: %zd\n", param); |
| 526 } while (*input); |
| 527 |
| 528 return true; |
| 529 } |
| 530 |
| 464 /////////////////////////////////////////////////////////////////////// | 531 /////////////////////////////////////////////////////////////////////// |
| 465 // main | 532 // main |
| 466 | 533 |
| 467 int main(int argc, char *argv[]) { | 534 int main(int argc, char *argv[]) { |
| 468 const char *myname = argv[0]; | 535 const char *myname = argv[0]; |
| 469 int err_stage = 0; // an indicator for error exits | 536 int err_stage = 0; // an indicator for error exits |
| 537 GoogleBinaryBlockUtil util; |
| 470 | 538 |
| 471 // small parameter helper class | 539 // small parameter helper class |
| 472 class OptPropertyMap: public | 540 class OptPropertyMap: public |
| 473 std::map<GoogleBinaryBlockUtil::PROPINDEX, string> { | 541 std::map<GoogleBinaryBlockUtil::PROPINDEX, string> { |
| 474 public: | 542 public: |
| 475 bool set_new_value(GoogleBinaryBlockUtil::PROPINDEX id, const string &v) { | 543 bool set_new_value(GoogleBinaryBlockUtil::PROPINDEX id, const string &v) { |
| 476 if (find(id) != end()) | 544 if (find(id) != end()) |
| 477 return false; | 545 return false; |
| 478 | 546 |
| 479 (*this)[id] = v; | 547 (*this)[id] = v; |
| 480 return true; | 548 return true; |
| 481 } | 549 } |
| 482 }; | 550 }; |
| 483 OptPropertyMap opt_props; | 551 OptPropertyMap opt_props; |
| 484 | 552 |
| 485 struct GBBUtilOptions { | 553 struct GBBUtilOptions { |
| 486 bool get_mode, set_mode; | 554 bool get_mode, set_mode, create_mode; |
| 487 string input_fn, output_fn; | 555 string input_fn, output_fn; |
| 556 std::vector<uint32_t> create_param; |
| 488 } myopts; | 557 } myopts; |
| 489 myopts.get_mode = myopts.set_mode = false; | 558 myopts.get_mode = myopts.set_mode = myopts.create_mode = false; |
| 490 | 559 |
| 491 // snippets for getopt_long | 560 // snippets for getopt_long |
| 492 int option_index, opt; | 561 int option_index, opt; |
| 493 static struct option long_options[] = { | 562 static struct option long_options[] = { |
| 494 {"get", 0, NULL, 'g' }, | 563 {"get", 0, NULL, 'g' }, |
| 495 {"set", 0, NULL, 's' }, | 564 {"set", 0, NULL, 's' }, |
| 565 {"create", 1, NULL, 'c' }, |
| 496 {"output", 1, NULL, 'o' }, | 566 {"output", 1, NULL, 'o' }, |
| 497 {"hwid", 2, NULL, 'i' }, | 567 {"hwid", 2, NULL, 'i' }, |
| 498 {"rootkey", 1, NULL, 'k' }, | 568 {"rootkey", 1, NULL, 'k' }, |
| 499 {"bmpfv", 1, NULL, 'b' }, | 569 {"bmpfv", 1, NULL, 'b' }, |
| 500 {"recoverykey", 1, NULL, 'R' }, | 570 {"recoverykey", 1, NULL, 'R' }, |
| 501 { NULL, 0, NULL, 0 }, | 571 { NULL, 0, NULL, 0 }, |
| 502 }; | 572 }; |
| 503 | 573 |
| 504 // parse command line options | 574 // parse command line options |
| 505 while ((opt = getopt_long(argc, argv, "gso:i:k:b:", | 575 while ((opt = getopt_long(argc, argv, "gsc:o:i:k:b:", |
| 506 long_options, &option_index)) >= 0) { | 576 long_options, &option_index)) >= 0) { |
| 507 switch (opt) { | 577 switch (opt) { |
| 508 case 'g': | 578 case 'g': |
| 509 myopts.get_mode = true; | 579 myopts.get_mode = true; |
| 510 break; | 580 break; |
| 511 | 581 |
| 512 case 's': | 582 case 's': |
| 513 myopts.set_mode = true; | 583 myopts.set_mode = true; |
| 514 break; | 584 break; |
| 515 | 585 |
| 586 case 'c': |
| 587 myopts.create_mode = true; |
| 588 assert(optarg); |
| 589 if (!*optarg || !parse_creation_param(optarg, &myopts.create_param)) { |
| 590 printf("error: invalid creation parameter: %s\n", optarg); |
| 591 usagehelp_exit(myname); |
| 592 } |
| 593 break; |
| 594 |
| 516 case 'o': | 595 case 'o': |
| 517 myopts.output_fn = optarg; | 596 myopts.output_fn = optarg; |
| 518 break; | 597 break; |
| 519 | 598 |
| 520 case 'i': | 599 case 'i': |
| 521 if (!opt_props.set_new_value( | 600 if (!opt_props.set_new_value( |
| 522 GoogleBinaryBlockUtil::PROP_HWID, optarg ? optarg : "")) | 601 GoogleBinaryBlockUtil::PROP_HWID, optarg ? optarg : "")) |
| 523 usagehelp_exit(myname); | 602 usagehelp_exit(myname); |
| 524 break; | 603 break; |
| 525 | 604 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 558 | 637 |
| 559 // currently, the only parameter is 'input file'. | 638 // currently, the only parameter is 'input file'. |
| 560 if (argc == 1) { | 639 if (argc == 1) { |
| 561 myopts.input_fn = argv[0]; | 640 myopts.input_fn = argv[0]; |
| 562 } else { | 641 } else { |
| 563 usagehelp_exit(myname); | 642 usagehelp_exit(myname); |
| 564 } | 643 } |
| 565 | 644 |
| 566 // stage: complete parameter parsing and checking | 645 // stage: complete parameter parsing and checking |
| 567 err_stage++; | 646 err_stage++; |
| 568 if (myopts.get_mode == myopts.set_mode) { | 647 if (myopts.create_mode) { |
| 648 if (myopts.get_mode || myopts.set_mode) { |
| 649 printf("error: please assign only one mode from get/set/create.\n"); |
| 650 return err_stage; |
| 651 } |
| 652 if (!opt_props.empty() || myopts.create_param.empty()) { |
| 653 printf("error: creation parameter syntax error.\n"); |
| 654 return err_stage; |
| 655 } |
| 656 if (myopts.output_fn.empty()) { |
| 657 myopts.output_fn = myopts.input_fn; |
| 658 } |
| 659 } else if (myopts.get_mode == myopts.set_mode) { |
| 569 if (myopts.get_mode) { | 660 if (myopts.get_mode) { |
| 570 printf("error: please assign either get or set mode.\n"); | 661 printf("error: please assign either get or set mode.\n"); |
| 571 return err_stage; | 662 return err_stage; |
| 572 } else { | 663 } else { |
| 573 // enter 'get' mode by default, if not assigned. | 664 // enter 'get' mode by default, if not assigned. |
| 574 myopts.get_mode = true; | 665 myopts.get_mode = true; |
| 575 } | 666 } |
| 576 } | 667 } |
| 577 if (myopts.get_mode && !myopts.output_fn.empty()) { | 668 if (myopts.get_mode && !myopts.output_fn.empty()) { |
| 578 printf("error: get-mode does not create output files.\n"); | 669 printf("error: get-mode does not create output files.\n"); |
| 579 return err_stage; | 670 return err_stage; |
| 580 } | 671 } |
| 581 | 672 |
| 673 if (myopts.create_mode) { |
| 674 if (!util.create_new(myopts.create_param)) |
| 675 return err_stage; |
| 676 |
| 677 assert(!myopts.output_fn.empty()); |
| 678 if (!util.save_to_file(myopts.output_fn.c_str())) { |
| 679 printf("error: cannot create to file: %s\n", myopts.output_fn.c_str()); |
| 680 return err_stage; |
| 681 } else { |
| 682 printf("successfully created new GBB to: %s\n", myopts.output_fn.c_str()); |
| 683 } |
| 684 return 0; |
| 685 } |
| 686 |
| 582 // stage: load image files | 687 // stage: load image files |
| 583 err_stage++; | 688 err_stage++; |
| 584 GoogleBinaryBlockUtil util; | |
| 585 | |
| 586 assert(!myopts.input_fn.empty()); | 689 assert(!myopts.input_fn.empty()); |
| 587 if (!util.load_from_file(myopts.input_fn.c_str())) { | 690 if (!util.load_from_file(myopts.input_fn.c_str())) { |
| 588 printf("error: cannot load valid BIOS file: %s\n", myopts.input_fn.c_str()); | 691 printf("error: cannot load valid BIOS file: %s\n", myopts.input_fn.c_str()); |
| 589 return err_stage; | 692 return err_stage; |
| 590 } | 693 } |
| 591 | 694 |
| 592 // stage: processing by mode | 695 // stage: processing by mode |
| 593 err_stage++; | 696 err_stage++; |
| 594 if (myopts.get_mode) { | 697 if (myopts.get_mode) { |
| 595 // get mode | 698 // get mode |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 639 return err_stage; | 742 return err_stage; |
| 640 } else { | 743 } else { |
| 641 printf("successfully saved new image to: %s\n", myopts.output_fn.c_str()); | 744 printf("successfully saved new image to: %s\n", myopts.output_fn.c_str()); |
| 642 } | 745 } |
| 643 } | 746 } |
| 644 | 747 |
| 645 return 0; | 748 return 0; |
| 646 } | 749 } |
| 647 | 750 |
| 648 #endif // WITH_UTIL_MAIN | 751 #endif // WITH_UTIL_MAIN |
| OLD | NEW |