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 firmware screen block (BMPBLOCK) in GBB. | 5 // Utility for manipulating firmware screen block (BMPBLOCK) in GBB. |
6 // | 6 // |
7 | 7 |
8 #include "bmpblk_utility.h" | 8 #include "bmpblk_utility.h" |
9 | 9 |
10 #include <assert.h> | 10 #include <assert.h> |
11 #include <errno.h> | 11 #include <errno.h> |
12 #include <getopt.h> | 12 #include <getopt.h> |
13 #include <stdarg.h> | 13 #include <stdarg.h> |
14 #include <stdio.h> | 14 #include <stdio.h> |
15 #include <stdlib.h> | 15 #include <stdlib.h> |
16 #include <string.h> | 16 #include <string.h> |
17 #include <yaml.h> | 17 #include <yaml.h> |
18 | 18 |
| 19 extern "C" { |
| 20 #include "eficompress.h" |
| 21 } |
| 22 |
| 23 |
19 /* BMP header, used to validate image requirements | 24 /* BMP header, used to validate image requirements |
20 * See http://en.wikipedia.org/wiki/BMP_file_format | 25 * See http://en.wikipedia.org/wiki/BMP_file_format |
21 */ | 26 */ |
22 typedef struct { | 27 typedef struct { |
23 uint8_t CharB; // must be 'B' | 28 uint8_t CharB; // must be 'B' |
24 uint8_t CharM; // must be 'M' | 29 uint8_t CharM; // must be 'M' |
25 uint32_t Size; | 30 uint32_t Size; |
26 uint16_t Reserved[2]; | 31 uint16_t Reserved[2]; |
27 uint32_t ImageOffset; | 32 uint32_t ImageOffset; |
28 uint32_t HeaderSize; | 33 uint32_t HeaderSize; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
60 BmpBlockUtil::~BmpBlockUtil() { | 65 BmpBlockUtil::~BmpBlockUtil() { |
61 } | 66 } |
62 | 67 |
63 void BmpBlockUtil::initialize() { | 68 void BmpBlockUtil::initialize() { |
64 config_.config_filename.clear(); | 69 config_.config_filename.clear(); |
65 memset(&config_.header, '\0', BMPBLOCK_SIGNATURE_SIZE); | 70 memset(&config_.header, '\0', BMPBLOCK_SIGNATURE_SIZE); |
66 config_.images_map.clear(); | 71 config_.images_map.clear(); |
67 config_.screens_map.clear(); | 72 config_.screens_map.clear(); |
68 config_.localizations.clear(); | 73 config_.localizations.clear(); |
69 bmpblock_.clear(); | 74 bmpblock_.clear(); |
| 75 set_compression_ = false; |
| 76 compression_ = COMPRESS_NONE; |
| 77 } |
| 78 |
| 79 void BmpBlockUtil::force_compression(uint32_t compression) { |
| 80 compression_ = compression; |
| 81 set_compression_ = true; |
70 } | 82 } |
71 | 83 |
72 void BmpBlockUtil::load_from_config(const char *filename) { | 84 void BmpBlockUtil::load_from_config(const char *filename) { |
73 load_yaml_config(filename); | 85 load_yaml_config(filename); |
74 fill_bmpblock_header(); | 86 fill_bmpblock_header(); |
75 load_all_image_files(); | 87 load_all_image_files(); |
76 fill_all_image_infos(); | 88 fill_all_image_infos(); |
77 } | 89 } |
78 | 90 |
79 void BmpBlockUtil::load_yaml_config(const char *filename) { | 91 void BmpBlockUtil::load_yaml_config(const char *filename) { |
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
285 } | 297 } |
286 } | 298 } |
287 | 299 |
288 void BmpBlockUtil::load_all_image_files() { | 300 void BmpBlockUtil::load_all_image_files() { |
289 for (StrImageConfigMap::iterator it = config_.images_map.begin(); | 301 for (StrImageConfigMap::iterator it = config_.images_map.begin(); |
290 it != config_.images_map.end(); | 302 it != config_.images_map.end(); |
291 ++it) { | 303 ++it) { |
292 const string &content = read_image_file(it->second.filename.c_str()); | 304 const string &content = read_image_file(it->second.filename.c_str()); |
293 it->second.raw_content = content; | 305 it->second.raw_content = content; |
294 it->second.data.original_size = content.size(); | 306 it->second.data.original_size = content.size(); |
295 /* Use no compression as default */ | 307 switch(compression_) { |
296 it->second.data.compression = COMPRESS_NONE; | 308 case COMPRESS_NONE: |
297 it->second.compressed_content = content; | 309 it->second.data.compression = compression_; |
298 it->second.data.compressed_size = content.size(); | 310 it->second.compressed_content = content; |
| 311 it->second.data.compressed_size = content.size(); |
| 312 break; |
| 313 case COMPRESS_EFIv1: |
| 314 { |
| 315 // The content will always compress smaller (so sez the docs). |
| 316 uint32_t tmpsize = content.size(); |
| 317 uint8_t *tmpbuf = (uint8_t *)malloc(tmpsize); |
| 318 // The size of the compressed content is also returned. |
| 319 if (EFI_SUCCESS != EfiCompress((uint8_t *)content.c_str(), tmpsize, |
| 320 tmpbuf, &tmpsize)) { |
| 321 error("Unable to compress!\n"); |
| 322 } |
| 323 it->second.data.compression = compression_; |
| 324 it->second.compressed_content.assign((const char *)tmpbuf, tmpsize); |
| 325 it->second.data.compressed_size = tmpsize; |
| 326 free(tmpbuf); |
| 327 } |
| 328 break; |
| 329 default: |
| 330 error("Unsupported compression method attempted.\n"); |
| 331 } |
299 } | 332 } |
300 } | 333 } |
301 | 334 |
302 const string BmpBlockUtil::read_image_file(const char *filename) { | 335 const string BmpBlockUtil::read_image_file(const char *filename) { |
303 string content; | 336 string content; |
304 vector<char> buffer; | 337 vector<char> buffer; |
305 | 338 |
306 FILE *fp = fopen(filename, "rb"); | 339 FILE *fp = fopen(filename, "rb"); |
307 if (!fp) { | 340 if (!fp) { |
308 perror(filename); | 341 perror(filename); |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
402 config_.localizations[i].size()); | 435 config_.localizations[i].size()); |
403 } | 436 } |
404 config_.header.number_of_imageinfos = config_.images_map.size(); | 437 config_.header.number_of_imageinfos = config_.images_map.size(); |
405 } | 438 } |
406 | 439 |
407 void BmpBlockUtil::pack_bmpblock() { | 440 void BmpBlockUtil::pack_bmpblock() { |
408 bmpblock_.clear(); | 441 bmpblock_.clear(); |
409 | 442 |
410 /* Compute the ImageInfo offsets from start of BMPBLOCK. */ | 443 /* Compute the ImageInfo offsets from start of BMPBLOCK. */ |
411 uint32_t current_offset = sizeof(BmpBlockHeader) + | 444 uint32_t current_offset = sizeof(BmpBlockHeader) + |
412 sizeof(ScreenLayout) * config_.images_map.size(); | 445 sizeof(ScreenLayout) * config_.screens_map.size(); |
413 for (StrImageConfigMap::iterator it = config_.images_map.begin(); | 446 for (StrImageConfigMap::iterator it = config_.images_map.begin(); |
414 it != config_.images_map.end(); | 447 it != config_.images_map.end(); |
415 ++it) { | 448 ++it) { |
416 it->second.offset = current_offset; | 449 it->second.offset = current_offset; |
417 current_offset += sizeof(ImageInfo) + it->second.data.compressed_size; | 450 current_offset += sizeof(ImageInfo) + it->second.data.compressed_size; |
418 /* Make it 4-byte aligned. */ | 451 /* Make it 4-byte aligned. */ |
419 if ((current_offset & 3) > 0) { | 452 if ((current_offset & 3) > 0) { |
420 current_offset = (current_offset & ~3) + 4; | 453 current_offset = (current_offset & ~3) + 4; |
421 } | 454 } |
422 } | 455 } |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
500 " %s [-z NUM] -c YAML BMPBLOCK\n" | 533 " %s [-z NUM] -c YAML BMPBLOCK\n" |
501 "\n" | 534 "\n" |
502 " -z NUM = compression algorithm to use\n" | 535 " -z NUM = compression algorithm to use\n" |
503 " 0 = none\n" | 536 " 0 = none\n" |
504 " 1 = EFIv1\n" | 537 " 1 = EFIv1\n" |
505 " 2 = TBD\n" | 538 " 2 = TBD\n" |
506 "\n", prog_name); | 539 "\n", prog_name); |
507 printf( | 540 printf( |
508 "To display the contents of a BMPBLOCK:\n" | 541 "To display the contents of a BMPBLOCK:\n" |
509 "\n" | 542 "\n" |
510 " %s BMPBLOCK\n" | 543 " %s [-y] BMPBLOCK\n" |
| 544 "\n" |
| 545 " -y = display as yaml\n" |
511 "\n", prog_name); | 546 "\n", prog_name); |
512 printf( | 547 printf( |
513 "To unpack a BMPBLOCK file:\n" | 548 "To unpack a BMPBLOCK file:\n" |
514 "\n" | 549 "\n" |
515 " %s -x [-d DIR] [-f] BMPBLOCK\n" | 550 " %s -x [-d DIR] [-f] BMPBLOCK\n" |
516 "\n" | 551 "\n" |
517 " -d DIR = directory to use (default '.')\n" | 552 " -d DIR = directory to use (default '.')\n" |
518 " -f = force overwriting existing files\n" | 553 " -f = force overwriting existing files\n" |
519 "\n", prog_name); | 554 "\n", prog_name); |
520 exit(1); | 555 exit(1); |
521 } | 556 } |
522 | 557 |
523 /////////////////////////////////////////////////////////////////////// | 558 /////////////////////////////////////////////////////////////////////// |
524 // main | 559 // main |
525 | 560 |
526 int main(int argc, char *argv[]) { | 561 int main(int argc, char *argv[]) { |
527 | 562 |
528 const char *prog_name = strrchr(argv[0], '/'); | 563 const char *prog_name = strrchr(argv[0], '/'); |
529 if (prog_name) | 564 if (prog_name) |
530 prog_name++; | 565 prog_name++; |
531 else | 566 else |
532 prog_name = argv[0]; | 567 prog_name = argv[0]; |
533 | 568 |
534 int force = 0, extract_mode = 0; | 569 int overwrite = 0, extract_mode = 0; |
535 int compression = 0; | 570 int compression = 0; |
| 571 int set_compression = 0; |
536 const char *config_fn = 0, *bmpblock_fn = 0, *extract_dir = "."; | 572 const char *config_fn = 0, *bmpblock_fn = 0, *extract_dir = "."; |
| 573 int show_as_yaml = 0; |
537 | 574 |
538 int opt; | 575 int opt; |
539 opterr = 0; // quiet | 576 opterr = 0; // quiet |
540 int errorcnt = 0; | 577 int errorcnt = 0; |
541 char *e = 0; | 578 char *e = 0; |
542 while ((opt = getopt(argc, argv, ":c:xz:fd:")) != -1) { | 579 while ((opt = getopt(argc, argv, ":c:xz:fd:y")) != -1) { |
543 switch (opt) { | 580 switch (opt) { |
544 case 'c': | 581 case 'c': |
545 config_fn = optarg; | 582 config_fn = optarg; |
546 break; | 583 break; |
547 case 'x': | 584 case 'x': |
548 extract_mode = 1; | 585 extract_mode = 1; |
549 break; | 586 break; |
| 587 case 'y': |
| 588 show_as_yaml = 1; |
| 589 break; |
550 case 'z': | 590 case 'z': |
551 compression = (int)strtoul(optarg, &e, 0); | 591 compression = (int)strtoul(optarg, &e, 0); |
552 if (!*optarg || (e && *e)) { | 592 if (!*optarg || (e && *e)) { |
553 fprintf(stderr, "%s: invalid argument to -%c: \"%s\"\n", | 593 fprintf(stderr, "%s: invalid argument to -%c: \"%s\"\n", |
554 prog_name, opt, optarg); | 594 prog_name, opt, optarg); |
555 errorcnt++; | 595 errorcnt++; |
556 } | 596 } |
557 if (compression >= MAX_COMPRESS) { | 597 if (compression >= MAX_COMPRESS) { |
558 fprintf(stderr, "%s: compression type must be less than %d\n", | 598 fprintf(stderr, "%s: compression type must be less than %d\n", |
559 prog_name, compression); | 599 prog_name, MAX_COMPRESS); |
560 errorcnt++; | 600 errorcnt++; |
561 } | 601 } |
| 602 set_compression = 1; |
562 break; | 603 break; |
563 case 'f': | 604 case 'f': |
564 force = 1; | 605 overwrite = 1; |
565 break; | 606 break; |
566 case 'd': | 607 case 'd': |
567 extract_dir= optarg; | 608 extract_dir= optarg; |
568 break; | 609 break; |
569 case ':': | 610 case ':': |
570 fprintf(stderr, "%s: missing argument to -%c\n", | 611 fprintf(stderr, "%s: missing argument to -%c\n", |
571 prog_name, optopt); | 612 prog_name, optopt); |
572 errorcnt++; | 613 errorcnt++; |
573 break; | 614 break; |
574 default: | 615 default: |
(...skipping 12 matching lines...) Expand all Loading... |
587 fprintf(stderr, "%s: missing BMPBLOCK name\n", prog_name); | 628 fprintf(stderr, "%s: missing BMPBLOCK name\n", prog_name); |
588 errorcnt++; | 629 errorcnt++; |
589 } | 630 } |
590 | 631 |
591 if (errorcnt) | 632 if (errorcnt) |
592 usagehelp_exit(prog_name); | 633 usagehelp_exit(prog_name); |
593 | 634 |
594 BmpBlockUtil util; | 635 BmpBlockUtil util; |
595 | 636 |
596 if (config_fn) { | 637 if (config_fn) { |
597 printf("compression is %d\n", compression); | 638 if (set_compression) |
| 639 util.force_compression(compression); |
598 util.load_from_config(config_fn); | 640 util.load_from_config(config_fn); |
599 util.pack_bmpblock(); | 641 util.pack_bmpblock(); |
600 util.write_to_bmpblock(bmpblock_fn); | 642 util.write_to_bmpblock(bmpblock_fn); |
601 printf("The BMPBLOCK is sucessfully created in: %s.\n", | |
602 bmpblock_fn); | |
603 } | 643 } |
604 | 644 |
605 else if (extract_mode) { | 645 else if (extract_mode) { |
606 return extract_bmpblock(bmpblock_fn, extract_dir, force); | 646 return dump_bmpblock(bmpblock_fn, 1, extract_dir, overwrite); |
607 printf("extract parts from %s into %s %s overwriting\n", | 647 } else { |
608 bmpblock_fn, extract_dir, force ? "with" : "without"); | 648 return dump_bmpblock(bmpblock_fn, show_as_yaml, 0, 0); |
609 /* TODO(waihong): Implement the list mode. */ | |
610 error("Extract mode hasn't been implemented yet.\n"); | |
611 } | |
612 | |
613 else { | |
614 return display_bmpblock(bmpblock_fn); | |
615 printf("display content of %s\n", bmpblock_fn); | |
616 /* TODO(waihong): Implement the list mode. */ | |
617 error("List mode hasn't been implemented yet.\n"); | |
618 } | 649 } |
619 | 650 |
620 return 0; | 651 return 0; |
621 } | 652 } |
622 | 653 |
623 #endif // WITH_UTIL_MAIN | 654 #endif // WITH_UTIL_MAIN |
OLD | NEW |