| 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> |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 148 last_found_pos++; // for next iteration | 148 last_found_pos++; // for next iteration |
| 149 } | 149 } |
| 150 | 150 |
| 151 return found_signatures; | 151 return found_signatures; |
| 152 } | 152 } |
| 153 | 153 |
| 154 // uility function for load_gbb_header to check property range | 154 // uility function for load_gbb_header to check property range |
| 155 static bool check_property_range(uint32_t off, uint32_t sz, | 155 static bool check_property_range(uint32_t off, uint32_t sz, |
| 156 uint32_t hdr_sz, uint32_t max_sz, | 156 uint32_t hdr_sz, uint32_t max_sz, |
| 157 const char *prop_name, bool verbose) { | 157 const char *prop_name, bool verbose) { |
| 158 // for backward compatibility, we allow zero entry here. |
| 159 if (off == 0 && sz == 0) { |
| 160 if (verbose) |
| 161 fprintf(stderr, " warning: property %s is EMPTY.\n", prop_name); |
| 162 return true; |
| 163 } |
| 164 |
| 158 if (off + sz > max_sz) { | 165 if (off + sz > max_sz) { |
| 159 if (verbose) | 166 if (verbose) |
| 160 fprintf(stderr, " error: property %s exceed GBB.\n", prop_name); | 167 fprintf(stderr, " error: property %s exceed GBB.\n", prop_name); |
| 161 return false; | 168 return false; |
| 162 } | 169 } |
| 163 | 170 |
| 164 if (off < hdr_sz) { | 171 if (off < hdr_sz) { |
| 165 if (verbose) | 172 if (verbose) |
| 166 fprintf(stderr, " error: property %s overlap GBB header.\n", prop_name); | 173 fprintf(stderr, " error: property %s overlap GBB header.\n", prop_name); |
| 167 return false; | 174 return false; |
| (...skipping 30 matching lines...) Expand all Loading... |
| 198 return false; | 205 return false; |
| 199 } | 206 } |
| 200 | 207 |
| 201 if (h.header_size < GBB_HEADER_SIZE) { | 208 if (h.header_size < GBB_HEADER_SIZE) { |
| 202 if (verbose) | 209 if (verbose) |
| 203 fprintf(stderr, " error: incompatible header size (%d < %d)\n", | 210 fprintf(stderr, " error: incompatible header size (%d < %d)\n", |
| 204 h.header_size, GBB_HEADER_SIZE); | 211 h.header_size, GBB_HEADER_SIZE); |
| 205 return false; | 212 return false; |
| 206 } | 213 } |
| 207 | 214 |
| 208 // verify location of properties | 215 // verify properties |
| 209 if (!check_property_range(h.hwid_offset, h.hwid_size, | 216 for (int i = 0; i < PROP_RANGE; i++) { |
| 210 h.header_size, block_size, "hwid", verbose) || | 217 uint32_t off, size; |
| 211 !check_property_range(h.rootkey_offset, h.rootkey_size, | 218 const char *name; |
| 212 h.header_size, block_size, "rootkey", verbose) || | 219 |
| 213 !check_property_range(h.bmpfv_offset, h.bmpfv_size, | 220 if (!find_property(static_cast<PROPINDEX>(i), |
| 214 h.header_size, block_size, "bmpfv", verbose)) { | 221 &off, &size, &name)) { |
| 215 return false; | 222 assert(!"invalid property."); |
| 223 return false; |
| 224 } |
| 225 |
| 226 if (!check_property_range(off, size, |
| 227 h.header_size, block_size, name, verbose)) |
| 228 return false; |
| 216 } | 229 } |
| 217 | 230 |
| 218 return true; | 231 return true; |
| 219 } | 232 } |
| 220 | 233 |
| 221 bool GoogleBinaryBlockUtil::find_property(PROPINDEX i, | 234 bool GoogleBinaryBlockUtil::find_property(PROPINDEX i, |
| 222 uint32_t *poffset, | 235 uint32_t *poffset, |
| 223 uint32_t *psize) const { | 236 uint32_t *psize, |
| 237 const char** pname) const { |
| 224 switch (i) { | 238 switch (i) { |
| 225 case PROP_HWID: | 239 case PROP_HWID: |
| 226 *poffset = header_.hwid_offset; | 240 *poffset = header_.hwid_offset; |
| 227 *psize = header_.hwid_size; | 241 *psize = header_.hwid_size; |
| 242 if (pname) |
| 243 *pname = "hardware_id"; |
| 228 break; | 244 break; |
| 229 | 245 |
| 230 case PROP_ROOTKEY: | 246 case PROP_ROOTKEY: |
| 231 *poffset = header_.rootkey_offset; | 247 *poffset = header_.rootkey_offset; |
| 232 *psize = header_.rootkey_size; | 248 *psize = header_.rootkey_size; |
| 249 if (pname) |
| 250 *pname = "root_key"; |
| 233 break; | 251 break; |
| 234 | 252 |
| 235 case PROP_BMPFV: | 253 case PROP_BMPFV: |
| 236 *poffset = header_.bmpfv_offset; | 254 *poffset = header_.bmpfv_offset; |
| 237 *psize = header_.bmpfv_size; | 255 *psize = header_.bmpfv_size; |
| 256 if (pname) |
| 257 *pname = "bmp_fv"; |
| 238 break; | 258 break; |
| 239 | 259 |
| 240 default: | 260 default: |
| 241 assert(!"invalid property index."); | 261 assert(!"invalid property index."); |
| 242 return false; | 262 return false; |
| 243 } | 263 } |
| 244 | 264 |
| 245 return true; | 265 return true; |
| 246 } | 266 } |
| 247 | 267 |
| 248 bool GoogleBinaryBlockUtil::set_property(PROPINDEX i, const string &value) { | 268 bool GoogleBinaryBlockUtil::set_property(PROPINDEX i, const string &value) { |
| 249 uint32_t prop_size; | 269 uint32_t prop_size; |
| 250 uint32_t prop_offset; | 270 uint32_t prop_offset; |
| 271 const char *prop_name; |
| 251 | 272 |
| 252 assert(is_valid_gbb); | 273 assert(is_valid_gbb); |
| 253 | 274 |
| 254 if (!find_property(i, &prop_offset, &prop_size)) { | 275 if (!find_property(i, &prop_offset, &prop_size, &prop_name)) { |
| 255 if (verbose) | 276 if (verbose) |
| 256 fprintf(stderr, " internal error: unknown property (%d).\n", | 277 fprintf(stderr, " internal error: unknown property (%d).\n", |
| 257 static_cast<int>(i)); | 278 static_cast<int>(i)); |
| 258 return false; | 279 return false; |
| 259 } | 280 } |
| 260 | 281 |
| 261 if (prop_size < value.size()) { | 282 if (prop_size < value.size()) { |
| 262 if (verbose) | 283 if (verbose) |
| 263 fprintf(stderr, " error: value size (%zu) exceed capacity (%u).\n", | 284 fprintf(stderr, " error: value size (%zu) exceed property capacity " |
| 264 value.size(), prop_size); | 285 "(%u): %s\n", value.size(), prop_size, prop_name); |
| 265 return false; | 286 return false; |
| 266 } | 287 } |
| 267 | 288 |
| 268 if (i == PROP_HWID && prop_size == value.size()) { | 289 if (i == PROP_HWID && prop_size == value.size()) { |
| 269 // special case: this is NUL-terminated so it's better to keep one more \0 | 290 // special case: this is NUL-terminated so it's better to keep one more \0 |
| 270 if (verbose) | 291 if (verbose) |
| 271 fprintf(stderr, "error: NUL-terminated string exceed capacity (%d)\n", | 292 fprintf(stderr, "error: NUL-terminated string exceed capacity (%d): %s\n", |
| 272 prop_size); | 293 prop_size, prop_name); |
| 273 return false; | 294 return false; |
| 274 } | 295 } |
| 275 | 296 |
| 276 string::iterator dest = file_content_.begin() + header_offset_ + prop_offset; | 297 string::iterator dest = file_content_.begin() + header_offset_ + prop_offset; |
| 277 file_content_.replace(dest, dest+prop_size, prop_size, '\0'); // wipe first | 298 file_content_.replace(dest, dest+prop_size, prop_size, '\0'); // wipe first |
| 278 std::copy(value.begin(), value.end(), dest); | 299 std::copy(value.begin(), value.end(), dest); |
| 279 | 300 |
| 280 return true; | 301 return true; |
| 281 } | 302 } |
| 282 | 303 |
| 283 string GoogleBinaryBlockUtil::get_property(PROPINDEX i) const { | 304 string GoogleBinaryBlockUtil::get_property(PROPINDEX i) const { |
| 284 uint32_t prop_size; | 305 uint32_t prop_size; |
| 285 uint32_t prop_offset; | 306 uint32_t prop_offset; |
| 307 const char *prop_name; |
| 286 | 308 |
| 287 assert(is_valid_gbb); | 309 assert(is_valid_gbb); |
| 288 | 310 |
| 289 if (!find_property(i, &prop_offset, &prop_size)) { | 311 if (!find_property(i, &prop_offset, &prop_size, &prop_name)) { |
| 290 if (verbose) | 312 if (verbose) |
| 291 fprintf(stderr, " internal error: unknown property (%d).\n", | 313 fprintf(stderr, " internal error: unknown property (%d).\n", |
| 292 static_cast<int>(i)); | 314 static_cast<int>(i)); |
| 293 return ""; | 315 return ""; |
| 294 } | 316 } |
| 295 | 317 |
| 318 // check range again to allow empty value (for compatbility) |
| 319 if (prop_offset == 0 && prop_size == 0) { |
| 320 if (verbose) |
| 321 fprintf(stderr, " warning: empty property (%d): %s.\n", |
| 322 static_cast<int>(i), prop_name); |
| 323 return ""; |
| 324 } |
| 325 |
| 296 string::const_iterator dest = file_content_.begin() + | 326 string::const_iterator dest = file_content_.begin() + |
| 297 header_offset_ + prop_offset; | 327 header_offset_ + prop_offset; |
| 298 return string(dest, dest + prop_size); | 328 return string(dest, dest + prop_size); |
| 299 } | 329 } |
| 300 | 330 |
| 331 string GoogleBinaryBlockUtil::get_property_name(PROPINDEX i) const { |
| 332 uint32_t unused_off, unused_size; |
| 333 const char *prop_name; |
| 334 |
| 335 if (!find_property(i, &unused_off, &unused_size, &prop_name)) { |
| 336 if (verbose) |
| 337 fprintf(stderr, " internal error: unknown property (%d).\n", |
| 338 static_cast<int>(i)); |
| 339 assert(!"invalid property index."); |
| 340 return ""; |
| 341 } |
| 342 |
| 343 return prop_name; |
| 344 } |
| 345 |
| 301 bool GoogleBinaryBlockUtil::set_hwid(const char *hwid) { | 346 bool GoogleBinaryBlockUtil::set_hwid(const char *hwid) { |
| 302 return set_property(PROP_HWID, hwid); | 347 return set_property(PROP_HWID, hwid); |
| 303 } | 348 } |
| 304 | 349 |
| 305 bool GoogleBinaryBlockUtil::set_rootkey(const std::string &value) { | 350 bool GoogleBinaryBlockUtil::set_rootkey(const std::string &value) { |
| 306 return set_property(PROP_ROOTKEY, value); | 351 return set_property(PROP_ROOTKEY, value); |
| 307 } | 352 } |
| 308 | 353 |
| 309 bool GoogleBinaryBlockUtil::set_bmpfv(const string &value) { | 354 bool GoogleBinaryBlockUtil::set_bmpfv(const string &value) { |
| 310 return set_property(PROP_BMPFV, value); | 355 return set_property(PROP_BMPFV, value); |
| 311 } | 356 } |
| 312 | 357 |
| 313 } // namespace vboot_reference | 358 } // namespace vboot_reference |
| 314 | 359 |
| 315 #ifdef WITH_UTIL_MAIN | 360 #ifdef WITH_UTIL_MAIN |
| 316 | 361 |
| 317 /////////////////////////////////////////////////////////////////////// | 362 /////////////////////////////////////////////////////////////////////// |
| 318 // command line utilities | 363 // command line utilities |
| 319 | 364 |
| 365 #include <map> |
| 366 |
| 367 using vboot_reference::GoogleBinaryBlockUtil; |
| 368 |
| 320 // utility function: provide usage of this utility and exit. | 369 // utility function: provide usage of this utility and exit. |
| 321 static void usagehelp_exit(const char *prog_name) { | 370 static void usagehelp_exit(const char *prog_name) { |
| 322 printf( | 371 printf( |
| 323 "Utility to manage Google Binary Block (GBB)\n" | 372 "Utility to manage Google Binary Block (GBB)\n" |
| 324 "Usage: %s [-g|-s] [OPTIONS] bios_file [output_file]\n\n" | 373 "Usage: %s [-g|-s] [OPTIONS] bios_file [output_file]\n" |
| 325 "-g, --get \tGet (read) from bios_file, " | 374 "\n" |
| 375 "GET MODE:\n" |
| 376 "-g, --get (default)\tGet (read) from bios_file, " |
| 326 "with following options:\n" | 377 "with following options:\n" |
| 327 " --hwid \tReport hardware id (default).\n" | 378 " --hwid \tReport hardware id (default).\n" |
| 328 " -k, --rootkey=FILE \tFile name to export Root Key.\n" | 379 " -k, --rootkey=FILE \tFile name to export Root Key.\n" |
| 329 " -b, --bmpfv=FILE \tFile name to export Bitmap FV.\n" | 380 " -b, --bmpfv=FILE \tFile name to export Bitmap FV.\n" |
| 330 "\n" | 381 "\n" |
| 382 "SET MODE:\n" |
| 331 "-s, --set \tSet (write) to bios_file, " | 383 "-s, --set \tSet (write) to bios_file, " |
| 332 "with following options:\n" | 384 "with following options:\n" |
| 385 " -o, --output=FILE \tNew file name for ouptput.\n" |
| 333 " -i, --hwid=HWID \tThe new hardware id to be changed.\n" | 386 " -i, --hwid=HWID \tThe new hardware id to be changed.\n" |
| 334 " -k, --rootkey=FILE \tFile name of new Root Key.\n" | 387 " -k, --rootkey=FILE \tFile name of new Root Key.\n" |
| 335 " -b, --bmpfv=FILE \tFile name of new Bitmap FV\n" | 388 " -b, --bmpfv=FILE \tFile name of new Bitmap FV.\n" |
| 336 "\n" | 389 "\n" |
| 337 " SAMPLE:\n" | 390 "SAMPLE:\n" |
| 338 " %s -g bios.bin\n" | 391 " %s -g bios.bin\n" |
| 339 " %s --set --hwid='New Model' -k key.bin bios.bin newbios.bin\n" | 392 " %s --set --hwid='New Model' -k key.bin bios.bin newbios.bin\n" |
| 340 , prog_name, prog_name, prog_name); | 393 , prog_name, prog_name, prog_name); |
| 341 exit(1); | 394 exit(1); |
| 342 } | 395 } |
| 343 | 396 |
| 344 // utility function: export a property from GBB to given file. | 397 // utility function: export a property from GBB to given file. |
| 398 // if filename was empty, export to console (screen). |
| 345 // return true on success, otherwise false. | 399 // return true on success, otherwise false. |
| 346 static bool export_property_to_file(const string &filename, | 400 static bool export_property(GoogleBinaryBlockUtil::PROPINDEX idx, |
| 347 const char *name, const string &value) { | 401 const string &filename, |
| 348 assert(!filename.empty()); | 402 const GoogleBinaryBlockUtil &util) { |
| 349 const char *fn = filename.c_str(); | 403 string prop_name = util.get_property_name(idx), |
| 404 value = util.get_property(idx); |
| 405 const char *name = prop_name.c_str(); |
| 350 | 406 |
| 351 if (!write_nonempty_file(fn, value)) { | 407 if (filename.empty()) { |
| 352 fprintf(stderr, "error: failed to export %s to file: %s\n", name, fn); | 408 // write to console |
| 353 return false; | 409 printf("%s: %s\n", name, value.c_str()); |
| 410 } else { |
| 411 const char *fn = filename.c_str(); |
| 412 |
| 413 if (!write_nonempty_file(fn, value)) { |
| 414 fprintf(stderr, "error: failed to export %s to file: %s\n", name, fn); |
| 415 return false; |
| 416 } |
| 417 printf(" - exported %s to file: %s\n", name, fn); |
| 354 } | 418 } |
| 355 | 419 |
| 356 printf(" - exported %s to file: %s\n", name, fn); | |
| 357 return true; | 420 return true; |
| 358 } | 421 } |
| 359 | 422 |
| 360 // utility function: import a property to GBB by given file. | 423 // utility function: import a property to GBB by given source (file or string). |
| 361 // return true on success, otherwise false. | 424 // return true on success, otherwise false. |
| 362 // is succesfully imported into GBB. | 425 // is succesfully imported into GBB. |
| 363 static bool import_property_from_file( | 426 static bool import_property( |
| 364 const string &filename, const char *name, | 427 GoogleBinaryBlockUtil::PROPINDEX idx, const string &source, |
| 365 bool (vboot_reference::GoogleBinaryBlockUtil::*setter)(const string &value), | 428 bool source_as_file, GoogleBinaryBlockUtil *putil) { |
| 366 vboot_reference::GoogleBinaryBlockUtil *putil) { | 429 assert(!source.empty()); |
| 367 assert(!filename.empty()); | 430 string prop_name = putil->get_property_name(idx); |
| 368 | 431 |
| 369 printf(" - import %s from %s: ", name, filename.c_str()); | 432 if (source_as_file) { |
| 370 string v = read_nonempty_file(filename.c_str()); | 433 printf(" - import %s from %s: ", prop_name.c_str(), source.c_str()); |
| 371 if (v.empty()) { | 434 string v = read_nonempty_file(source.c_str()); |
| 372 printf("invalid file.\n"); | 435 if (v.empty()) { |
| 373 return false; | 436 printf("invalid file.\n"); |
| 437 return false; |
| 438 } |
| 439 if (!putil->set_property(idx, v)) { |
| 440 printf("invalid content.\n"); |
| 441 return false; |
| 442 } |
| 443 printf("success.\n"); |
| 444 } else { |
| 445 // source as string |
| 446 string old_value = putil->get_property(idx); |
| 447 bool result = putil->set_property(idx, source); |
| 448 printf(" - %s changed from '%s' to '%s': %s\n", |
| 449 prop_name.c_str(), old_value.c_str(), source.c_str(), |
| 450 result ? "success" : "failed"); |
| 451 if (!result) |
| 452 return false; |
| 374 } | 453 } |
| 375 | 454 |
| 376 if (!(putil->*setter)(v)) { | |
| 377 printf("invalid content.\n"); | |
| 378 return false; | |
| 379 } | |
| 380 | |
| 381 printf("success.\n"); | |
| 382 return true; | 455 return true; |
| 383 } | 456 } |
| 384 | 457 |
| 385 /////////////////////////////////////////////////////////////////////// | 458 /////////////////////////////////////////////////////////////////////// |
| 386 // main | 459 // main |
| 387 | 460 |
| 388 int main(int argc, char *argv[]) { | 461 int main(int argc, char *argv[]) { |
| 389 const char *myname = argv[0]; | 462 const char *myname = argv[0]; |
| 390 int err_stage = 0; // an indicator for error exits | 463 int err_stage = 0; // an indicator for error exits |
| 391 | 464 |
| 465 // small parameter helper class |
| 466 class OptPropertyMap: public |
| 467 std::map<GoogleBinaryBlockUtil::PROPINDEX, string> { |
| 468 public: |
| 469 bool set_new_value(GoogleBinaryBlockUtil::PROPINDEX id, const string &v) { |
| 470 if (find(id) != end()) |
| 471 return false; |
| 472 (*this)[id] = v; |
| 473 return true; |
| 474 } |
| 475 }; |
| 476 OptPropertyMap opt_props; |
| 477 |
| 392 struct GBBUtilOptions { | 478 struct GBBUtilOptions { |
| 393 bool get_mode, set_mode; | 479 bool get_mode, set_mode; |
| 394 bool use_hwid, use_rootkey, use_bmpfv; | 480 string input_fn, output_fn; |
| 395 string hwid, rootkey_fn, bmpfv_fn; | |
| 396 } myopts; | 481 } myopts; |
| 397 | |
| 398 myopts.get_mode = myopts.set_mode = false; | 482 myopts.get_mode = myopts.set_mode = false; |
| 399 myopts.use_hwid = myopts.use_rootkey = myopts.use_bmpfv = false; | |
| 400 | 483 |
| 401 // snippets for getopt_long | 484 // snippets for getopt_long |
| 402 int option_index, opt; | 485 int option_index, opt; |
| 403 static struct option long_options[] = { | 486 static struct option long_options[] = { |
| 404 {"get", 0, NULL, 'g' }, | 487 {"get", 0, NULL, 'g' }, |
| 405 {"set", 0, NULL, 's' }, | 488 {"set", 0, NULL, 's' }, |
| 406 {"hwid", 2, NULL, 'i' }, | 489 {"output", 1, NULL, 'o' }, |
| 490 {"hwid", 2, NULL, 'i' }, |
| 407 {"rootkey", 1, NULL, 'k' }, | 491 {"rootkey", 1, NULL, 'k' }, |
| 408 {"bmpfv", 1, NULL, 'b' }, | 492 {"bmpfv", 1, NULL, 'b' }, |
| 409 { NULL, 0, NULL, 0 }, | 493 { NULL, 0, NULL, 0 }, |
| 410 }; | 494 }; |
| 411 int opt_props = 0; // number of assigned properties. | |
| 412 | 495 |
| 413 // parse command line options | 496 // parse command line options |
| 414 while ((opt = getopt_long(argc, argv, "gsi:k:b:", | 497 while ((opt = getopt_long(argc, argv, "gso:i:k:b:", |
| 415 long_options, &option_index)) >= 0) { | 498 long_options, &option_index)) >= 0) { |
| 416 switch (opt) { | 499 switch (opt) { |
| 417 case 'g': | 500 case 'g': |
| 418 myopts.get_mode = true; | 501 myopts.get_mode = true; |
| 419 break; | 502 break; |
| 420 | 503 |
| 421 case 's': | 504 case 's': |
| 422 myopts.set_mode = true; | 505 myopts.set_mode = true; |
| 423 break; | 506 break; |
| 424 | 507 |
| 508 case 'o': |
| 509 myopts.output_fn = optarg; |
| 510 break; |
| 511 |
| 425 case 'i': | 512 case 'i': |
| 426 opt_props++; | 513 if (!opt_props.set_new_value( |
| 427 myopts.use_hwid = true; | 514 GoogleBinaryBlockUtil::PROP_HWID, optarg ? optarg : "")) |
| 428 if (optarg) | 515 usagehelp_exit(myname); |
| 429 myopts.hwid = optarg; | |
| 430 break; | 516 break; |
| 431 | 517 |
| 432 case 'k': | 518 case 'k': |
| 433 opt_props++; | 519 if (!opt_props.set_new_value( |
| 434 myopts.use_rootkey = true; | 520 GoogleBinaryBlockUtil::PROP_ROOTKEY, optarg)) |
| 435 myopts.rootkey_fn = optarg; | 521 usagehelp_exit(myname); |
| 436 break; | 522 break; |
| 437 | 523 |
| 438 case 'b': | 524 case 'b': |
| 439 opt_props++; | 525 if (!opt_props.set_new_value( |
| 440 myopts.use_bmpfv = true; | 526 GoogleBinaryBlockUtil::PROP_BMPFV, optarg)) |
| 441 myopts.bmpfv_fn = optarg; | 527 usagehelp_exit(myname); |
| 442 break; | 528 break; |
| 443 | 529 |
| 444 default: | 530 default: |
| 445 case '?': | 531 case '?': |
| 446 usagehelp_exit(myname); | 532 usagehelp_exit(myname); |
| 447 break; | 533 break; |
| 448 } | 534 } |
| 449 } | 535 } |
| 450 argc -= optind; | 536 argc -= optind; |
| 451 argv += optind; | 537 argv += optind; |
| 452 | 538 |
| 453 // check parameters configuration | 539 // adjust non-dashed parameters |
| 454 if (!(argc == 1 || (myopts.set_mode && argc == 2))) | 540 if (myopts.output_fn.empty() && argc == 2) { |
| 541 myopts.output_fn = argv[1]; |
| 542 argc--; |
| 543 } |
| 544 |
| 545 // currently, the only parameter is 'input file'. |
| 546 if (argc == 1) { |
| 547 myopts.input_fn = argv[0]; |
| 548 } else { |
| 455 usagehelp_exit(myname); | 549 usagehelp_exit(myname); |
| 550 } |
| 456 | 551 |
| 457 // stage: parameter parsing | 552 // stage: complete parameter parsing and checking |
| 458 err_stage++; | 553 err_stage++; |
| 459 if (myopts.get_mode == myopts.set_mode) { | 554 if (myopts.get_mode == myopts.set_mode) { |
| 460 printf("error: please assign either get or set mode.\n"); | 555 if (myopts.get_mode) { |
| 556 printf("error: please assign either get or set mode.\n"); |
| 557 return err_stage; |
| 558 } else { |
| 559 // enter 'get' mode by default, if not assigned. |
| 560 myopts.get_mode = true; |
| 561 } |
| 562 } |
| 563 if (myopts.get_mode && !myopts.output_fn.empty()) { |
| 564 printf("error: get-mode does not create output files.\n"); |
| 461 return err_stage; | 565 return err_stage; |
| 462 } | 566 } |
| 463 | 567 |
| 464 // stage: load image files | 568 // stage: load image files |
| 465 err_stage++; | 569 err_stage++; |
| 466 vboot_reference::GoogleBinaryBlockUtil util; | 570 GoogleBinaryBlockUtil util; |
| 467 const char *input_filename = argv[0], | |
| 468 *output_filename= (argc > 1) ? argv[1] : argv[0]; | |
| 469 | 571 |
| 470 if (!util.load_from_file(input_filename)) { | 572 assert(!myopts.input_fn.empty()); |
| 471 printf("error: cannot load valid BIOS file: %s\n", input_filename); | 573 if (!util.load_from_file(myopts.input_fn.c_str())) { |
| 574 printf("error: cannot load valid BIOS file: %s\n", myopts.input_fn.c_str()); |
| 472 return err_stage; | 575 return err_stage; |
| 473 } | 576 } |
| 474 | 577 |
| 475 // stage: processing by mode | 578 // stage: processing by mode |
| 476 err_stage++; | 579 err_stage++; |
| 477 if (myopts.get_mode) { | 580 if (myopts.get_mode) { |
| 478 // get mode | 581 // get mode |
| 479 if (opt_props < 1) // enable hwid by default | 582 if (opt_props.empty()) // enable hwid by default |
| 480 myopts.use_hwid = true; | 583 opt_props.set_new_value(GoogleBinaryBlockUtil::PROP_HWID, ""); |
| 481 | 584 |
| 482 if (myopts.use_hwid) | 585 for (OptPropertyMap::const_iterator i = opt_props.begin(); |
| 483 printf("Hardware ID: %s\n", util.get_hwid().c_str()); | 586 i != opt_props.end(); |
| 484 if (myopts.use_rootkey) | 587 i++) { |
| 485 export_property_to_file(myopts.rootkey_fn, "rootkey", util.get_rootkey()); | 588 export_property(i->first, i->second, util); |
| 486 if (myopts.use_bmpfv) | 589 } |
| 487 export_property_to_file(myopts.bmpfv_fn, "bmpfv", util.get_bmpfv()); | 590 |
| 488 } else { | 591 } else { |
| 489 // set mode | 592 // set mode |
| 490 assert(myopts.set_mode); | 593 assert(myopts.set_mode); |
| 491 if (opt_props < 1) { | 594 |
| 595 if (opt_props.empty()) { |
| 492 printf("nothing to change. abort.\n"); | 596 printf("nothing to change. abort.\n"); |
| 493 return err_stage; | 597 return err_stage; |
| 494 } | 598 } |
| 495 | 599 |
| 496 // HWID does not come from file, so update it direcly here. | 600 for (OptPropertyMap::const_iterator i = opt_props.begin(); |
| 497 if (myopts.use_hwid) { | 601 i != opt_props.end(); |
| 498 string old_hwid = util.get_hwid(); | 602 i++) { |
| 499 if (!util.set_hwid(myopts.hwid.c_str())) { | 603 bool source_as_file = true; |
| 500 printf("error: inproper hardware id: %s\n", | 604 |
| 501 myopts.hwid.c_str()); | 605 // the hwid command line parameter was a simple string. |
| 606 if (i->first == GoogleBinaryBlockUtil::PROP_HWID) |
| 607 source_as_file = false; |
| 608 |
| 609 if (!import_property(i->first, i->second, source_as_file, &util)) { |
| 610 printf("error: cannot set properties. abort.\n"); |
| 502 return err_stage; | 611 return err_stage; |
| 503 } | 612 } |
| 504 printf(" - Hardware id changed: %s -> %s.\n", | |
| 505 old_hwid.c_str(), util.get_hwid().c_str()); | |
| 506 } | |
| 507 | |
| 508 // import other properties from file | |
| 509 if ((myopts.use_rootkey && | |
| 510 !import_property_from_file(myopts.rootkey_fn, "rootkey", | |
| 511 &vboot_reference::GoogleBinaryBlockUtil::set_rootkey, &util)) || | |
| 512 (myopts.use_bmpfv && | |
| 513 !import_property_from_file(myopts.bmpfv_fn, "bmpfv", | |
| 514 &vboot_reference::GoogleBinaryBlockUtil::set_bmpfv, &util))) { | |
| 515 printf("error: cannot set new properties. abort.\n"); | |
| 516 return err_stage; | |
| 517 } | 613 } |
| 518 | 614 |
| 519 // stage: write output | 615 // stage: write output |
| 520 err_stage++; | 616 err_stage++; |
| 521 if (!util.save_to_file(output_filename)) { | 617 |
| 522 printf("error: cannot save to file: %s\n", output_filename); | 618 // use input filename (overwrite) by default |
| 619 if (myopts.output_fn.empty()) |
| 620 myopts.output_fn = myopts.input_fn; |
| 621 |
| 622 assert(!myopts.output_fn.empty()); |
| 623 if (!util.save_to_file(myopts.output_fn.c_str())) { |
| 624 printf("error: cannot save to file: %s\n", myopts.output_fn.c_str()); |
| 523 return err_stage; | 625 return err_stage; |
| 524 } else { | 626 } else { |
| 525 printf("successfully saved new image to: %s\n", output_filename); | 627 printf("successfully saved new image to: %s\n", myopts.output_fn.c_str()); |
| 526 } | 628 } |
| 527 } | 629 } |
| 528 | 630 |
| 529 return 0; | 631 return 0; |
| 530 } | 632 } |
| 531 | 633 |
| 532 #endif // WITH_UTIL_MAIN | 634 #endif // WITH_UTIL_MAIN |
| 533 | 635 |
| OLD | NEW |