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 |