| 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 |