1d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
2d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson// Use of this source code is governed by a BSD-style license that can be
3d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson// found in the LICENSE file.
4d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson//
5d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson// Utility for manipulating firmware screen block (BMPBLOCK) in GBB.
6d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson//
7d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson
8d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson#include <assert.h>
9d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson#include <errno.h>
10d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson#include <getopt.h>
11ee2bc91d4393796721dc8a48d3510e3352f2b893Tom Wai-Hong Tam#include <lzma.h>
12d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson#include <stdarg.h>
130c3ba249abb1dc60f5ebabccf84ff13206440b83Bill Richardson#include <stdint.h>
14d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson#include <stdio.h>
15d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson#include <stdlib.h>
16d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson#include <string.h>
17d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson#include <yaml.h>
18d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson
190c3ba249abb1dc60f5ebabccf84ff13206440b83Bill Richardson#include "bmpblk_utility.h"
200c3ba249abb1dc60f5ebabccf84ff13206440b83Bill Richardson#include "image_types.h"
210c3ba249abb1dc60f5ebabccf84ff13206440b83Bill Richardson#include "vboot_api.h"
220c3ba249abb1dc60f5ebabccf84ff13206440b83Bill Richardson
2361362d65fcdd6f6aff90fc5be51237b39cfeb9aeBill Richardsonextern "C" {
2461362d65fcdd6f6aff90fc5be51237b39cfeb9aeBill Richardson#include "eficompress.h"
2561362d65fcdd6f6aff90fc5be51237b39cfeb9aeBill Richardson}
2661362d65fcdd6f6aff90fc5be51237b39cfeb9aeBill Richardson
2761362d65fcdd6f6aff90fc5be51237b39cfeb9aeBill Richardson
28d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardsonstatic void error(const char *format, ...) {
29d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson  va_list ap;
30d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson  va_start(ap, format);
31d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson  fprintf(stderr, "ERROR: ");
32d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson  vfprintf(stderr, format, ap);
33d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson  va_end(ap);
34d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson  exit(1);
35d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson}
36d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson
37d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson///////////////////////////////////////////////////////////////////////
38d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson// BmpBlock Utility implementation
39d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson
40d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardsonnamespace vboot_reference {
41d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson
4254e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson  BmpBlockUtil::BmpBlockUtil(bool debug) {
4354e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    major_version_ = BMPBLOCK_MAJOR_VERSION;
4454e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    minor_version_ = BMPBLOCK_MINOR_VERSION;
4554e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    config_.config_filename.clear();
4654e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    memset(&config_.header, '\0', BMPBLOCK_SIGNATURE_SIZE);
4754e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    config_.images_map.clear();
4854e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    config_.screens_map.clear();
4954e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    config_.localizations.clear();
5054e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    bmpblock_.clear();
5154e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    set_compression_ = false;
5254e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    compression_ = COMPRESS_NONE;
5354e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    debug_ = debug;
540a9977e161ce6ad6b11935dfb05ae840bf758078Bill Richardson    render_hwid_ = true;
550a9977e161ce6ad6b11935dfb05ae840bf758078Bill Richardson    support_font_ = true;
560a9977e161ce6ad6b11935dfb05ae840bf758078Bill Richardson    got_font_ = false;
570a9977e161ce6ad6b11935dfb05ae840bf758078Bill Richardson    got_rtol_font_ = false;
5854e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson  }
59d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson
6054e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson  BmpBlockUtil::~BmpBlockUtil() {
6154e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson  }
62d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson
6354e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson  void BmpBlockUtil::force_compression(uint32_t compression) {
6454e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    compression_ = compression;
6554e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    set_compression_ = true;
6654e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson  }
6761362d65fcdd6f6aff90fc5be51237b39cfeb9aeBill Richardson
6854e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson  void BmpBlockUtil::load_from_config(const char *filename) {
6954e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    load_yaml_config(filename);
7054e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    fill_bmpblock_header();
7154e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    load_all_image_files();
7254e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson  }
73d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson
7454e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson  void BmpBlockUtil::load_yaml_config(const char *filename) {
7554e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    yaml_parser_t parser;
76d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson
7754e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    config_.config_filename = filename;
7854e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    config_.images_map.clear();
7954e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    config_.screens_map.clear();
8054e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    config_.localizations.clear();
818ba3d790e16c6e0759686b1bd8b25db778c3fc9fBill Richardson    config_.locale_names.clear();
82d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson
8354e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    FILE *fp = fopen(filename, "rb");
8454e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    if (!fp) {
8554e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      perror(filename);
8654e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      exit(errno);
8754e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    }
88d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson
8954e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    yaml_parser_initialize(&parser);
9054e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    yaml_parser_set_input_file(&parser, fp);
9154e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    parse_config(&parser);
9254e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    yaml_parser_delete(&parser);
9354e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    fclose(fp);
94d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson
95d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson
962e0226309d1407e0968a6b699e99126c98407319Bill Richardson    // TODO: Check the yaml file for self-consistency. Warn on any problems.
9754e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    // All images should be used somewhere in the screens.
9854e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    // All images referenced in the screens should be defined.
9954e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    // All screens should be used somewhere in the localizations.
10054e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    // All screens referenced in the localizations should be defined.
1018ba3d790e16c6e0759686b1bd8b25db778c3fc9fBill Richardson    // The number of localizations should match the number of locale_index
102d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson
10354e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    if (debug_) {
10454e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      printf("%ld image_names\n", config_.image_names.size());
10554e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      for (unsigned int i = 0; i < config_.image_names.size(); ++i) {
10654e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson        printf(" %d: \"%s\"\n", i, config_.image_names[i].c_str());
10754e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      }
10854e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      printf("%ld images_map\n", config_.images_map.size());
10954e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      for (StrImageConfigMap::iterator it = config_.images_map.begin();
11054e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson           it != config_.images_map.end();
11154e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson           ++it) {
1120a9977e161ce6ad6b11935dfb05ae840bf758078Bill Richardson        printf("  \"%s\": filename=\"%s\" offset=0x%x tag=%d fmt=%d\n",
11354e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson               it->first.c_str(),
11454e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson               it->second.filename.c_str(),
11554e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson               it->second.offset,
1160a9977e161ce6ad6b11935dfb05ae840bf758078Bill Richardson               it->second.data.tag,
1170a9977e161ce6ad6b11935dfb05ae840bf758078Bill Richardson               it->second.data.format);
11854e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      }
11954e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      printf("%ld screens_map\n", config_.screens_map.size());
12054e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      for (StrScreenConfigMap::iterator it = config_.screens_map.begin();
12154e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson           it != config_.screens_map.end();
12254e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson           ++it) {
12354e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson        printf("  \"%s\":\n", it->first.c_str());
12454e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson        for (int k=0; k<MAX_IMAGE_IN_LAYOUT; k++) {
12554e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson          printf("    %d: \"%s\" (%d,%d) ofs=0x%x\n",
12654e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson                 k,
12754e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson                 it->second.image_names[k].c_str(),
12854e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson                 it->second.data.images[k].x,
12954e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson                 it->second.data.images[k].y,
13054e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson                 it->second.data.images[k].image_info_offset);
13154e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson        }
13254e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      }
13354e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    }
13454e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson  }
135d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson
13654e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson  void BmpBlockUtil::expect_event(yaml_parser_t *parser,
13754e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson                                  const yaml_event_type_e type) {
13854e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    yaml_event_t event;
139d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson    yaml_parser_parse(parser, &event);
14054e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    if (event.type != type) {
14154e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      error("Syntax error.\n");
14254e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    }
14354e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    yaml_event_delete(&event);
14454e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson  }
14554e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson
14654e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson  void BmpBlockUtil::parse_config(yaml_parser_t *parser) {
14754e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    expect_event(parser, YAML_STREAM_START_EVENT);
14854e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    expect_event(parser, YAML_DOCUMENT_START_EVENT);
14954e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    parse_first_layer(parser);
15054e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    expect_event(parser, YAML_DOCUMENT_END_EVENT);
15154e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    expect_event(parser, YAML_STREAM_END_EVENT);
15254e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson  }
15354e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson
15454e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson  void BmpBlockUtil::parse_first_layer(yaml_parser_t *parser) {
15554e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    yaml_event_t event;
15654e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    string keyword;
15754e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    expect_event(parser, YAML_MAPPING_START_EVENT);
15854e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    for (;;) {
15954e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      yaml_parser_parse(parser, &event);
16054e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      switch (event.type) {
161d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson      case YAML_SCALAR_EVENT:
162d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson        keyword = (char*)event.data.scalar.value;
163d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson        if (keyword == "bmpblock") {
164d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson          parse_bmpblock(parser);
165a7209ee2de570a1404e6df247df4a68c72d16245Bill Richardson        } else if (keyword == "compression") {
166a7209ee2de570a1404e6df247df4a68c72d16245Bill Richardson          parse_compression(parser);
167d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson        } else if (keyword == "images") {
168d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson          parse_images(parser);
169d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson        } else if (keyword == "screens") {
170d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson          parse_screens(parser);
171d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson        } else if (keyword == "localizations") {
172d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson          parse_localizations(parser);
1738ba3d790e16c6e0759686b1bd8b25db778c3fc9fBill Richardson        } else if (keyword == "locale_index") {
1748ba3d790e16c6e0759686b1bd8b25db778c3fc9fBill Richardson          parse_locale_index(parser);
175d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson        }
176d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson        break;
177d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson      case YAML_MAPPING_END_EVENT:
178d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson        yaml_event_delete(&event);
179d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson        return;
180d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson      default:
181d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson        error("Syntax error in parsing config file.\n");
18254e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      }
18354e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      yaml_event_delete(&event);
184d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson    }
185d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson  }
186d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson
18754e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson  void BmpBlockUtil::parse_bmpblock(yaml_parser_t *parser) {
18854e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    yaml_event_t event;
18954e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    yaml_parser_parse(parser, &event);
19054e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    if (event.type != YAML_SCALAR_EVENT) {
19154e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      error("Syntax error in parsing bmpblock.\n");
19254e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    }
19354e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    string gotversion = (char*)event.data.scalar.value;
1943985f94fae52aa1df853f7d47388c67c3022e069Dave Parker    if (gotversion != "2.0") {
19554e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      error("Unsupported version specified in config file (%s)\n",
19654e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson            gotversion.c_str());
19754e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    }
19854e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    yaml_event_delete(&event);
199fc05bb854f2d38b714cec3924e3ade2d4fb84561Bill Richardson  }
200d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson
20154e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson  void BmpBlockUtil::parse_compression(yaml_parser_t *parser) {
20254e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    yaml_event_t event;
20354e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    yaml_parser_parse(parser, &event);
20454e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    if (event.type != YAML_SCALAR_EVENT) {
20554e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      error("Syntax error in parsing bmpblock.\n");
20654e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    }
20754e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    char *comp_str = (char *)event.data.scalar.value;
20854e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    char *e = 0;
20954e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    uint32_t comp = (uint32_t)strtoul(comp_str, &e, 0);
21054e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    if (!*comp_str || (e && *e) || comp >= MAX_COMPRESS) {
21154e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      error("Invalid compression specified in config file (%d)\n", comp);
21254e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    }
21354e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    if (!set_compression_) {
21454e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      compression_ = comp;
21554e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    }
21654e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    yaml_event_delete(&event);
217a7209ee2de570a1404e6df247df4a68c72d16245Bill Richardson  }
218a7209ee2de570a1404e6df247df4a68c72d16245Bill Richardson
21954e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson  void BmpBlockUtil::parse_images(yaml_parser_t *parser) {
22054e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    yaml_event_t event;
22154e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    string image_name, image_filename;
22254e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    expect_event(parser, YAML_MAPPING_START_EVENT);
22354e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    for (;;) {
22454e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      yaml_parser_parse(parser, &event);
22554e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      switch (event.type) {
226d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson      case YAML_SCALAR_EVENT:
227d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson        image_name = (char*)event.data.scalar.value;
228d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson        yaml_event_delete(&event);
229d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson        yaml_parser_parse(parser, &event);
230d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson        if (event.type != YAML_SCALAR_EVENT) {
231d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson          error("Syntax error in parsing images.\n");
232d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson        }
233d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson        image_filename = (char*)event.data.scalar.value;
234f82f941b803b0c28240913eb57b34ab4c6c6b96aBill Richardson        config_.image_names.push_back(image_name);
235d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson        config_.images_map[image_name] = ImageConfig();
236d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson        config_.images_map[image_name].filename = image_filename;
2370a9977e161ce6ad6b11935dfb05ae840bf758078Bill Richardson        if (image_name == RENDER_HWID) {
2380a9977e161ce6ad6b11935dfb05ae840bf758078Bill Richardson          got_font_ = true;
2390a9977e161ce6ad6b11935dfb05ae840bf758078Bill Richardson        }
2400a9977e161ce6ad6b11935dfb05ae840bf758078Bill Richardson        if (image_name == RENDER_HWID_RTOL) {
2410a9977e161ce6ad6b11935dfb05ae840bf758078Bill Richardson          got_rtol_font_ = true;
2420a9977e161ce6ad6b11935dfb05ae840bf758078Bill Richardson        }
243d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson        break;
244d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson      case YAML_MAPPING_END_EVENT:
245d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson        yaml_event_delete(&event);
246d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson        return;
247d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson      default:
248d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson        error("Syntax error in parsing images.\n");
24954e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      }
25054e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      yaml_event_delete(&event);
251d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson    }
252d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson  }
253d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson
25454e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson  void BmpBlockUtil::parse_layout(yaml_parser_t *parser, ScreenConfig &screen) {
25554e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    yaml_event_t event;
25654e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    int depth = 0, index1 = 0, index2 = 0;
25754e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    expect_event(parser, YAML_SEQUENCE_START_EVENT);
25854e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    for (;;) {
25954e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      yaml_parser_parse(parser, &event);
26054e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      switch (event.type) {
261d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson      case YAML_SEQUENCE_START_EVENT:
262d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson        depth++;
263d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson        break;
264d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson      case YAML_SCALAR_EVENT:
265d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson        switch (index2) {
26654e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson        case 0:
26754e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson          screen.data.images[index1].x = atoi((char*)event.data.scalar.value);
26854e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson          break;
26954e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson        case 1:
27054e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson          screen.data.images[index1].y = atoi((char*)event.data.scalar.value);
27154e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson          break;
27254e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson        case 2:
27354e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson          screen.image_names[index1] = (char*)event.data.scalar.value;
27454e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson          // Detect the special case where we're rendering the HWID string
2750a9977e161ce6ad6b11935dfb05ae840bf758078Bill Richardson          // instead of displaying a bitmap.  The image name may not
2760a9977e161ce6ad6b11935dfb05ae840bf758078Bill Richardson          // exist in the list of images (v1.1), but we will still need an
27754e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson          // ImageInfo struct to remember where to draw the text.
2780a9977e161ce6ad6b11935dfb05ae840bf758078Bill Richardson          // Note that v1.2 requires that the image name DOES exist, because
2790a9977e161ce6ad6b11935dfb05ae840bf758078Bill Richardson          // the corresponding file is used to hold the font glpyhs.
28054e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson          if (render_hwid_) {
28154e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson            if (screen.image_names[index1] == RENDER_HWID) {
28254e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson              config_.images_map[RENDER_HWID].data.tag = TAG_HWID;
2830a9977e161ce6ad6b11935dfb05ae840bf758078Bill Richardson              if (support_font_ && !got_font_)
2840a9977e161ce6ad6b11935dfb05ae840bf758078Bill Richardson                error("Font required in 'image:' section for %s\n",
2850a9977e161ce6ad6b11935dfb05ae840bf758078Bill Richardson                      RENDER_HWID);
28654e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson            } else if (screen.image_names[index1] == RENDER_HWID_RTOL) {
28754e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson              config_.images_map[RENDER_HWID_RTOL].data.tag = TAG_HWID_RTOL;
2880a9977e161ce6ad6b11935dfb05ae840bf758078Bill Richardson              if (support_font_ && !got_rtol_font_)
2890a9977e161ce6ad6b11935dfb05ae840bf758078Bill Richardson                error("Font required in 'image:' section for %s\n",
2900a9977e161ce6ad6b11935dfb05ae840bf758078Bill Richardson                      RENDER_HWID_RTOL);
29154e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson            }
29254e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson          }
29354e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson          break;
29454e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson        default:
29554e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson          error("Syntax error in parsing layout\n");
296d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson        }
297d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson        index2++;
298d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson        break;
299d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson      case YAML_SEQUENCE_END_EVENT:
300d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson        if (depth == 1) {
301d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson          index1++;
302d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson          index2 = 0;
303d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson        } else if (depth == 0) {
304d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson          yaml_event_delete(&event);
305d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson          return;
306d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson        }
307d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson        depth--;
308d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson        break;
309d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson      default:
310d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson        error("Syntax error in paring layout.\n");
31154e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      }
31254e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      yaml_event_delete(&event);
313d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson    }
314d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson  }
315d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson
31654e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson  void BmpBlockUtil::parse_screens(yaml_parser_t *parser) {
31754e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    yaml_event_t event;
31854e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    string screen_name;
31954e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    expect_event(parser, YAML_MAPPING_START_EVENT);
32054e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    for (;;) {
32154e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      yaml_parser_parse(parser, &event);
32254e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      switch (event.type) {
323d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson      case YAML_SCALAR_EVENT:
324d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson        screen_name = (char*)event.data.scalar.value;
325d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson        config_.screens_map[screen_name] = ScreenConfig();
326d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson        parse_layout(parser, config_.screens_map[screen_name]);
327d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson        break;
328d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson      case YAML_MAPPING_END_EVENT:
329d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson        yaml_event_delete(&event);
330d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson        return;
331d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson      default:
332d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson        error("Syntax error in parsing screens.\n");
33354e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      }
33454e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      yaml_event_delete(&event);
335d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson    }
336d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson  }
337d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson
33854e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson  void BmpBlockUtil::parse_localizations(yaml_parser_t *parser) {
33954e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    yaml_event_t event;
34054e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    int depth = 0, index = 0;
34154e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    expect_event(parser, YAML_SEQUENCE_START_EVENT);
34254e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    for (;;) {
34354e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      yaml_parser_parse(parser, &event);
34454e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      switch (event.type) {
345d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson      case YAML_SEQUENCE_START_EVENT:
346d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson        config_.localizations.push_back(vector<string>());
347d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson        depth++;
348d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson        break;
349d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson      case YAML_SCALAR_EVENT:
350d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson        config_.localizations[index].push_back((char*)event.data.scalar.value);
351d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson        break;
352d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson      case YAML_SEQUENCE_END_EVENT:
353d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson        if (depth == 1) {
354d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson          index++;
355d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson        } else if (depth == 0) {
356d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson          yaml_event_delete(&event);
357d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson          return;
358d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson        }
359d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson        depth--;
360d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson        break;
361d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson      default:
362d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson        error("Syntax error in parsing localizations.\n");
36354e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      }
36454e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      yaml_event_delete(&event);
365d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson    }
366d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson  }
367d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson
3688ba3d790e16c6e0759686b1bd8b25db778c3fc9fBill Richardson  void BmpBlockUtil::parse_locale_index(yaml_parser_t *parser) {
3698ba3d790e16c6e0759686b1bd8b25db778c3fc9fBill Richardson    yaml_event_t event;
3708ba3d790e16c6e0759686b1bd8b25db778c3fc9fBill Richardson    expect_event(parser, YAML_SEQUENCE_START_EVENT);
3718ba3d790e16c6e0759686b1bd8b25db778c3fc9fBill Richardson    for (;;) {
3728ba3d790e16c6e0759686b1bd8b25db778c3fc9fBill Richardson      yaml_parser_parse(parser, &event);
3738ba3d790e16c6e0759686b1bd8b25db778c3fc9fBill Richardson      switch (event.type) {
3748ba3d790e16c6e0759686b1bd8b25db778c3fc9fBill Richardson      case YAML_SCALAR_EVENT:
3758ba3d790e16c6e0759686b1bd8b25db778c3fc9fBill Richardson        config_.locale_names.append((char*)event.data.scalar.value);
3768ba3d790e16c6e0759686b1bd8b25db778c3fc9fBill Richardson        config_.locale_names.append(1, (char)'\0'); // '\0' to delimit
3778ba3d790e16c6e0759686b1bd8b25db778c3fc9fBill Richardson        break;
3788ba3d790e16c6e0759686b1bd8b25db778c3fc9fBill Richardson      case YAML_SEQUENCE_END_EVENT:
3798ba3d790e16c6e0759686b1bd8b25db778c3fc9fBill Richardson        yaml_event_delete(&event);
3808ba3d790e16c6e0759686b1bd8b25db778c3fc9fBill Richardson        config_.locale_names.append(1, (char)'\0'); // double '\0' to terminate
3818ba3d790e16c6e0759686b1bd8b25db778c3fc9fBill Richardson        return;
3828ba3d790e16c6e0759686b1bd8b25db778c3fc9fBill Richardson      default:
3838ba3d790e16c6e0759686b1bd8b25db778c3fc9fBill Richardson        error("Syntax error in parsing localizations.\n");
3848ba3d790e16c6e0759686b1bd8b25db778c3fc9fBill Richardson      }
3858ba3d790e16c6e0759686b1bd8b25db778c3fc9fBill Richardson    }
3868ba3d790e16c6e0759686b1bd8b25db778c3fc9fBill Richardson  }
3878ba3d790e16c6e0759686b1bd8b25db778c3fc9fBill Richardson
38854e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson  void BmpBlockUtil::load_all_image_files() {
38954e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    for (unsigned int i = 0; i < config_.image_names.size(); i++) {
39054e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      StrImageConfigMap::iterator it =
39154e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson        config_.images_map.find(config_.image_names[i]);
39254e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      if (debug_) {
39354e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson        printf("loading image \"%s\" from \"%s\"\n",
39454e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson               config_.image_names[i].c_str(),
39554e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson               it->second.filename.c_str());
39654e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      }
39754e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      const string &content = read_image_file(it->second.filename.c_str());
39854e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      it->second.raw_content = content;
39954e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      it->second.data.original_size = content.size();
4000a9977e161ce6ad6b11935dfb05ae840bf758078Bill Richardson      it->second.data.format =
4010a9977e161ce6ad6b11935dfb05ae840bf758078Bill Richardson        identify_image_type(content.c_str(),
4020a9977e161ce6ad6b11935dfb05ae840bf758078Bill Richardson                            (uint32_t)content.size(), &it->second.data);
4030a9977e161ce6ad6b11935dfb05ae840bf758078Bill Richardson      if (FORMAT_INVALID == it->second.data.format) {
40454e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson        error("Unsupported image format in %s\n", it->second.filename.c_str());
40554e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      }
40654e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      switch(compression_) {
40754e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      case COMPRESS_NONE:
40854e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson        it->second.data.compression = compression_;
40954e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson        it->second.compressed_content = content;
41054e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson        it->second.data.compressed_size = content.size();
41154e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson        break;
41254e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      case COMPRESS_EFIv1:
41361362d65fcdd6f6aff90fc5be51237b39cfeb9aeBill Richardson      {
41461362d65fcdd6f6aff90fc5be51237b39cfeb9aeBill Richardson        // The content will always compress smaller (so sez the docs).
41561362d65fcdd6f6aff90fc5be51237b39cfeb9aeBill Richardson        uint32_t tmpsize = content.size();
41661362d65fcdd6f6aff90fc5be51237b39cfeb9aeBill Richardson        uint8_t *tmpbuf = (uint8_t *)malloc(tmpsize);
41761362d65fcdd6f6aff90fc5be51237b39cfeb9aeBill Richardson        // The size of the compressed content is also returned.
41861362d65fcdd6f6aff90fc5be51237b39cfeb9aeBill Richardson        if (EFI_SUCCESS != EfiCompress((uint8_t *)content.c_str(), tmpsize,
41961362d65fcdd6f6aff90fc5be51237b39cfeb9aeBill Richardson                                       tmpbuf, &tmpsize)) {
42061362d65fcdd6f6aff90fc5be51237b39cfeb9aeBill Richardson          error("Unable to compress!\n");
42161362d65fcdd6f6aff90fc5be51237b39cfeb9aeBill Richardson        }
42261362d65fcdd6f6aff90fc5be51237b39cfeb9aeBill Richardson        it->second.data.compression = compression_;
42361362d65fcdd6f6aff90fc5be51237b39cfeb9aeBill Richardson        it->second.compressed_content.assign((const char *)tmpbuf, tmpsize);
42461362d65fcdd6f6aff90fc5be51237b39cfeb9aeBill Richardson        it->second.data.compressed_size = tmpsize;
42561362d65fcdd6f6aff90fc5be51237b39cfeb9aeBill Richardson        free(tmpbuf);
42661362d65fcdd6f6aff90fc5be51237b39cfeb9aeBill Richardson      }
42761362d65fcdd6f6aff90fc5be51237b39cfeb9aeBill Richardson      break;
42854e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      case COMPRESS_LZMA1:
429ee2bc91d4393796721dc8a48d3510e3352f2b893Tom Wai-Hong Tam      {
430ee2bc91d4393796721dc8a48d3510e3352f2b893Tom Wai-Hong Tam        // Calculate the worst case of buffer size.
431ee2bc91d4393796721dc8a48d3510e3352f2b893Tom Wai-Hong Tam        uint32_t tmpsize = lzma_stream_buffer_bound(content.size());
432ee2bc91d4393796721dc8a48d3510e3352f2b893Tom Wai-Hong Tam        uint8_t *tmpbuf = (uint8_t *)malloc(tmpsize);
433ee2bc91d4393796721dc8a48d3510e3352f2b893Tom Wai-Hong Tam        lzma_stream stream = LZMA_STREAM_INIT;
434ee2bc91d4393796721dc8a48d3510e3352f2b893Tom Wai-Hong Tam        lzma_options_lzma options;
435ee2bc91d4393796721dc8a48d3510e3352f2b893Tom Wai-Hong Tam        lzma_ret result;
436ee2bc91d4393796721dc8a48d3510e3352f2b893Tom Wai-Hong Tam
437ee2bc91d4393796721dc8a48d3510e3352f2b893Tom Wai-Hong Tam        lzma_lzma_preset(&options, 9);
438ee2bc91d4393796721dc8a48d3510e3352f2b893Tom Wai-Hong Tam        result = lzma_alone_encoder(&stream, &options);
439ee2bc91d4393796721dc8a48d3510e3352f2b893Tom Wai-Hong Tam        if (result != LZMA_OK) {
440ee2bc91d4393796721dc8a48d3510e3352f2b893Tom Wai-Hong Tam          error("Unable to initialize easy encoder (error: %d)!\n", result);
441ee2bc91d4393796721dc8a48d3510e3352f2b893Tom Wai-Hong Tam        }
442ee2bc91d4393796721dc8a48d3510e3352f2b893Tom Wai-Hong Tam
443ee2bc91d4393796721dc8a48d3510e3352f2b893Tom Wai-Hong Tam        stream.next_in = (uint8_t *)content.data();
444ee2bc91d4393796721dc8a48d3510e3352f2b893Tom Wai-Hong Tam        stream.avail_in = content.size();
445ee2bc91d4393796721dc8a48d3510e3352f2b893Tom Wai-Hong Tam        stream.next_out = tmpbuf;
446ee2bc91d4393796721dc8a48d3510e3352f2b893Tom Wai-Hong Tam        stream.avail_out = tmpsize;
447ee2bc91d4393796721dc8a48d3510e3352f2b893Tom Wai-Hong Tam        result = lzma_code(&stream, LZMA_FINISH);
448ee2bc91d4393796721dc8a48d3510e3352f2b893Tom Wai-Hong Tam        if (result != LZMA_STREAM_END) {
449ee2bc91d4393796721dc8a48d3510e3352f2b893Tom Wai-Hong Tam          error("Unable to encode data (error: %d)!\n", result);
450ee2bc91d4393796721dc8a48d3510e3352f2b893Tom Wai-Hong Tam        }
451ee2bc91d4393796721dc8a48d3510e3352f2b893Tom Wai-Hong Tam
452ee2bc91d4393796721dc8a48d3510e3352f2b893Tom Wai-Hong Tam        it->second.data.compression = compression_;
453ee2bc91d4393796721dc8a48d3510e3352f2b893Tom Wai-Hong Tam        it->second.compressed_content.assign((const char *)tmpbuf,
454ee2bc91d4393796721dc8a48d3510e3352f2b893Tom Wai-Hong Tam                                             tmpsize - stream.avail_out);
455ee2bc91d4393796721dc8a48d3510e3352f2b893Tom Wai-Hong Tam        it->second.data.compressed_size = tmpsize - stream.avail_out;
456ee2bc91d4393796721dc8a48d3510e3352f2b893Tom Wai-Hong Tam        lzma_end(&stream);
457ee2bc91d4393796721dc8a48d3510e3352f2b893Tom Wai-Hong Tam        free(tmpbuf);
458ee2bc91d4393796721dc8a48d3510e3352f2b893Tom Wai-Hong Tam      }
459ee2bc91d4393796721dc8a48d3510e3352f2b893Tom Wai-Hong Tam      break;
46054e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      default:
46154e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson        error("Unsupported compression method attempted.\n");
46254e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      }
46361362d65fcdd6f6aff90fc5be51237b39cfeb9aeBill Richardson    }
464d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson  }
465d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson
46654e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson  const string BmpBlockUtil::read_image_file(const char *filename) {
46754e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    string content;
46854e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    vector<char> buffer;
469d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson
47054e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    FILE *fp = fopen(filename, "rb");
47154e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    if (!fp) {
472d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson      perror(filename);
47354e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      exit(errno);
474d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson    }
475d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson
47654e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    if (fseek(fp, 0, SEEK_END) == 0) {
47754e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      buffer.resize(ftell(fp));
47854e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      rewind(fp);
47954e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    }
480fc05bb854f2d38b714cec3924e3ade2d4fb84561Bill Richardson
48154e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    if (!buffer.empty()) {
48254e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      if(fread(&buffer[0], buffer.size(), 1, fp) != 1) {
48354e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson        perror(filename);
48454e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson        buffer.clear();
48554e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      } else {
48654e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson        content.assign(buffer.begin(), buffer.end());
48754e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      }
48854e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    }
489fc05bb854f2d38b714cec3924e3ade2d4fb84561Bill Richardson
49054e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    fclose(fp);
49154e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    return content;
49254e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson  }
493d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson
49454e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson  void BmpBlockUtil::fill_bmpblock_header() {
49554e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    memset(&config_.header, '\0', sizeof(config_.header));
49654e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    memcpy(&config_.header.signature, BMPBLOCK_SIGNATURE,
49754e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson           BMPBLOCK_SIGNATURE_SIZE);
49854e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    config_.header.major_version = major_version_;
49954e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    config_.header.minor_version = minor_version_;
50054e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    config_.header.number_of_localizations = config_.localizations.size();
50154e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    config_.header.number_of_screenlayouts = config_.localizations[0].size();
5026df3e33912baf2633ed27fce6fe166d87e2f04a8Bill Richardson    // NOTE: this is part of the yaml consistency check
50354e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    for (unsigned int i = 1; i < config_.localizations.size(); ++i) {
50454e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      assert(config_.header.number_of_screenlayouts ==
50554e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson             config_.localizations[i].size());
506d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson    }
50754e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    config_.header.number_of_imageinfos = config_.images_map.size();
5088ba3d790e16c6e0759686b1bd8b25db778c3fc9fBill Richardson    config_.header.locale_string_offset = 0; // Filled by pack_bmpblock()
509d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson  }
51054e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson
51154e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson  void BmpBlockUtil::pack_bmpblock() {
51254e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    bmpblock_.clear();
51354e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson
51454e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    /* Compute the ImageInfo offsets from start of BMPBLOCK. */
51554e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    uint32_t current_offset = sizeof(BmpBlockHeader) +
51654e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      sizeof(ScreenLayout) * (config_.header.number_of_localizations *
51754e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson                              config_.header.number_of_screenlayouts);
51854e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    for (StrImageConfigMap::iterator it = config_.images_map.begin();
51954e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson         it != config_.images_map.end();
52054e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson         ++it) {
52154e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      it->second.offset = current_offset;
52254e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      if (debug_)
5230a9977e161ce6ad6b11935dfb05ae840bf758078Bill Richardson        printf("  \"%s\": filename=\"%s\" offset=0x%x tag=%d fmt=%d\n",
52454e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson               it->first.c_str(),
52554e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson               it->second.filename.c_str(),
52654e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson               it->second.offset,
5270a9977e161ce6ad6b11935dfb05ae840bf758078Bill Richardson               it->second.data.tag,
5280a9977e161ce6ad6b11935dfb05ae840bf758078Bill Richardson               it->second.data.format);
52954e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      current_offset += sizeof(ImageInfo) +
53054e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson        it->second.data.compressed_size;
53154e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      /* Make it 4-byte aligned. */
53254e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      if ((current_offset & 3) > 0) {
53354e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson        current_offset = (current_offset & ~3) + 4;
534d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson      }
535d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson    }
5368ba3d790e16c6e0759686b1bd8b25db778c3fc9fBill Richardson    /* And leave room for the locale_index string */
5378ba3d790e16c6e0759686b1bd8b25db778c3fc9fBill Richardson    if (config_.locale_names.size()) {
5388ba3d790e16c6e0759686b1bd8b25db778c3fc9fBill Richardson      config_.header.locale_string_offset = current_offset;
5398ba3d790e16c6e0759686b1bd8b25db778c3fc9fBill Richardson      current_offset += config_.locale_names.size();
5408ba3d790e16c6e0759686b1bd8b25db778c3fc9fBill Richardson    }
5418ba3d790e16c6e0759686b1bd8b25db778c3fc9fBill Richardson
54254e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    bmpblock_.resize(current_offset);
543d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson
54454e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    /* Fill BmpBlockHeader struct. */
54554e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    string::iterator current_filled = bmpblock_.begin();
54654e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    std::copy(reinterpret_cast<char*>(&config_.header),
54754e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson              reinterpret_cast<char*>(&config_.header + 1),
548d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson              current_filled);
54954e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    current_filled += sizeof(config_.header);
55054e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    current_offset = sizeof(config_.header);
55154e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson
55254e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    /* Fill all ScreenLayout structs. */
55354e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    for (unsigned int i = 0; i < config_.localizations.size(); ++i) {
55454e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      for (unsigned int j = 0; j < config_.localizations[i].size(); ++j) {
55554e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson        ScreenConfig &screen = config_.screens_map[config_.localizations[i][j]];
55654e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson        for (unsigned int k = 0;
55754e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson             k < MAX_IMAGE_IN_LAYOUT && !screen.image_names[k].empty();
55854e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson             ++k) {
55954e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson          if (config_.images_map.find(screen.image_names[k]) ==
56054e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson              config_.images_map.end()) {
56154e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson            error("Invalid image name \"%s\"\n", screen.image_names[k].c_str());
56254e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson          }
56354e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson          if (debug_)
56454e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson            printf("i=%d j=%d k=%d=\"%s\" (%d,%d) ofs=%x\n", i,j,k,
56554e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson                   screen.image_names[k].c_str(),
56654e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson                   screen.data.images[k].x, screen.data.images[k].y,
56754e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson                   config_.images_map[screen.image_names[k]].offset
56854e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson              );
56954e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson          screen.data.images[k].image_info_offset =
57054e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson            config_.images_map[screen.image_names[k]].offset;
57154e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson        }
57254e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson        std::copy(reinterpret_cast<char*>(&screen.data),
57354e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson                  reinterpret_cast<char*>(&screen.data + 1),
57454e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson                  current_filled);
57554e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson        current_filled += sizeof(screen.data);
57654e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson        if (debug_)
57754e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson          printf("S: current offset is 0x%08x\n", current_offset);
57854e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson        current_offset += sizeof(screen.data);
57954e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      }
58054e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    }
58154e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson
58254e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    /* Fill all ImageInfo structs and image contents. */
58354e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    for (StrImageConfigMap::iterator it = config_.images_map.begin();
58454e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson         it != config_.images_map.end();
58554e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson         ++it) {
58654e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      current_filled = bmpblock_.begin() + it->second.offset;
58754e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      current_offset = it->second.offset;
58854e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      if (debug_)
58954e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson        printf("I0: current offset is 0x%08x\n", current_offset);
59054e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      std::copy(reinterpret_cast<char*>(&it->second.data),
59154e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson                reinterpret_cast<char*>(&it->second.data + 1),
59254e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson                current_filled);
59354e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      current_filled += sizeof(it->second.data);
59454e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      current_offset += sizeof(it->second.data);
59554e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      if (debug_)
59654e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson        printf("I1: current offset is 0x%08x (len %ld)\n",
59754e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson               current_offset, it->second.compressed_content.length());
59854e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      std::copy(it->second.compressed_content.begin(),
59954e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson                it->second.compressed_content.end(),
60054e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson                current_filled);
60154e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    }
6028ba3d790e16c6e0759686b1bd8b25db778c3fc9fBill Richardson
6038ba3d790e16c6e0759686b1bd8b25db778c3fc9fBill Richardson    /* Fill in locale_names. */
6048ba3d790e16c6e0759686b1bd8b25db778c3fc9fBill Richardson    if (config_.header.locale_string_offset) {
6058ba3d790e16c6e0759686b1bd8b25db778c3fc9fBill Richardson      current_offset = config_.header.locale_string_offset;
6068ba3d790e16c6e0759686b1bd8b25db778c3fc9fBill Richardson      current_filled = bmpblock_.begin() + current_offset;
6078ba3d790e16c6e0759686b1bd8b25db778c3fc9fBill Richardson      if (debug_)
6088ba3d790e16c6e0759686b1bd8b25db778c3fc9fBill Richardson        printf("locale_names: offset 0x%08x (len %ld)\n",
6098ba3d790e16c6e0759686b1bd8b25db778c3fc9fBill Richardson               current_offset, config_.locale_names.size());
6108ba3d790e16c6e0759686b1bd8b25db778c3fc9fBill Richardson      std::copy(config_.locale_names.begin(),
6118ba3d790e16c6e0759686b1bd8b25db778c3fc9fBill Richardson                config_.locale_names.end(),
6128ba3d790e16c6e0759686b1bd8b25db778c3fc9fBill Richardson                current_filled);
6138ba3d790e16c6e0759686b1bd8b25db778c3fc9fBill Richardson    }
614d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson  }
615d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson
61654e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson  void BmpBlockUtil::write_to_bmpblock(const char *filename) {
61754e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    assert(!bmpblock_.empty());
618d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson
61954e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    FILE *fp = fopen(filename, "wb");
62054e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    if (!fp) {
62154e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      perror(filename);
62254e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      exit(errno);
62354e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    }
624d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson
62554e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    int r = fwrite(bmpblock_.c_str(), bmpblock_.size(), 1, fp);
62654e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    fclose(fp);
62754e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    if (r != 1) {
62854e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      perror(filename);
62954e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      exit(errno);
63054e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    }
631d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson  }
632d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson
633d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson}  // namespace vboot_reference
634d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson
63517f8d341099120da78a6ca71165834eefb0960edRandall Spangler#ifndef FOR_LIBRARY
636d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson
63754e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson  //////////////////////////////////////////////////////////////////////////////
63854e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson  // Command line utilities.
639794d4d44db984759466b5b6779833e2d5281e527Bill Richardson
64054e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson  extern "C" {
641794d4d44db984759466b5b6779833e2d5281e527Bill Richardson#include "bmpblk_util.h"
64254e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson  }
643d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson
64454e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson  using vboot_reference::BmpBlockUtil;
64554e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson
64654e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson  // utility function: provide usage of this utility and exit.
64754e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson  static void usagehelp_exit(const char *prog_name) {
64854e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    printf(
64954e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      "\n"
65054e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      "To create a new BMPBLOCK file using config from YAML file:\n"
65154e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      "\n"
65254e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      "  %s [-z NUM] -c YAML BMPBLOCK\n"
65354e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      "\n"
65454e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      "    -z NUM  = compression algorithm to use\n"
65554e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      "              0 = none\n"
65654e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      "              1 = EFIv1\n"
65754e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      "              2 = LZMA1\n"
65854e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      "\n", prog_name);
65954e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    printf(
66054e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      "To display the contents of a BMPBLOCK:\n"
66154e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      "\n"
66254e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      "  %s [-y] BMPBLOCK\n"
66354e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      "\n"
66454e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      "    -y  = display as yaml\n"
66554e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      "\n", prog_name);
66654e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    printf(
66754e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      "To unpack a BMPBLOCK file:\n"
66854e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      "\n"
66954e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      "  %s -x [-d DIR] [-f] BMPBLOCK\n"
67054e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      "\n"
67154e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      "    -d DIR  = directory to use (default '.')\n"
67254e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      "    -f      = force overwriting existing files\n"
67354e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      "\n", prog_name);
67454e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    exit(1);
67554e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson  }
676d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson
67754e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson  ///////////////////////////////////////////////////////////////////////
67854e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson  // main
67954e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson
68054e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson  int main(int argc, char *argv[]) {
68154e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson
68254e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    const char *prog_name = strrchr(argv[0], '/');
68354e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    if (prog_name)
68454e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      prog_name++;
68554e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    else
68654e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      prog_name = argv[0];
68754e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson
68854e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    int overwrite = 0, extract_mode = 0;
68954e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    int compression = 0;
69054e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    int set_compression = 0;
69154e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    const char *config_fn = 0, *bmpblock_fn = 0, *extract_dir = ".";
69254e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    int show_as_yaml = 0;
69354e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    bool debug = false;
69454e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson
69554e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    int opt;
69654e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    opterr = 0;                           // quiet
69754e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    int errorcnt = 0;
69854e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    char *e = 0;
69954e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    while ((opt = getopt(argc, argv, ":c:xz:fd:yD")) != -1) {
70054e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      switch (opt) {
70154e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      case 'c':
70254e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson        config_fn = optarg;
70354e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson        break;
70454e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      case 'x':
70554e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson        extract_mode = 1;
70654e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson        break;
70754e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      case 'y':
70854e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson        show_as_yaml = 1;
70954e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson        break;
71054e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      case 'z':
71154e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson        compression = (int)strtoul(optarg, &e, 0);
71254e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson        if (!*optarg || (e && *e)) {
71354e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson          fprintf(stderr, "%s: invalid argument to -%c: \"%s\"\n",
71454e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson                  prog_name, opt, optarg);
71554e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson          errorcnt++;
71654e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson        }
71754e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson        if (compression >= MAX_COMPRESS) {
71854e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson          fprintf(stderr, "%s: compression type must be less than %d\n",
71954e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson                  prog_name, MAX_COMPRESS);
72054e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson          errorcnt++;
72154e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson        }
72254e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson        set_compression = 1;
72354e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson        break;
72454e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      case 'f':
72554e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson        overwrite = 1;
72654e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson        break;
72754e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      case 'd':
72854e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson        extract_dir= optarg;
72954e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson        break;
73054e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      case 'D':
73154e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson        debug = true;
73254e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson        break;
73354e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      case ':':
73454e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson        fprintf(stderr, "%s: missing argument to -%c\n",
73554e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson                prog_name, optopt);
736794d4d44db984759466b5b6779833e2d5281e527Bill Richardson        errorcnt++;
73754e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson        break;
73854e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      default:
73954e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson        fprintf(stderr, "%s: unrecognized switch: -%c\n",
74054e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson                prog_name, optopt);
741794d4d44db984759466b5b6779833e2d5281e527Bill Richardson        errorcnt++;
74254e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson        break;
743794d4d44db984759466b5b6779833e2d5281e527Bill Richardson      }
74454e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    }
74554e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    argc -= optind;
74654e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    argv += optind;
74754e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson
74854e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    if (argc >= 1) {
74954e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      bmpblock_fn = argv[0];
75054e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    } else {
75154e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      fprintf(stderr, "%s: missing BMPBLOCK name\n", prog_name);
752794d4d44db984759466b5b6779833e2d5281e527Bill Richardson      errorcnt++;
753d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson    }
754d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson
75554e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    if (errorcnt)
75654e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      usagehelp_exit(prog_name);
757794d4d44db984759466b5b6779833e2d5281e527Bill Richardson
75854e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    BmpBlockUtil util(debug);
759794d4d44db984759466b5b6779833e2d5281e527Bill Richardson
76054e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    if (config_fn) {
76154e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      if (set_compression)
76254e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson        util.force_compression(compression);
76354e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      util.load_from_config(config_fn);
76454e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      util.pack_bmpblock();
76554e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      util.write_to_bmpblock(bmpblock_fn);
76654e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    }
767d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson
76854e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    else if (extract_mode) {
76954e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      return dump_bmpblock(bmpblock_fn, 1, extract_dir, overwrite);
77054e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    } else {
77154e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson      return dump_bmpblock(bmpblock_fn, show_as_yaml, 0, 0);
77254e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    }
773d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson
77454e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson    return 0;
77554e95825b30d4f730cbd70c109fb6622dda6fbb8Bill Richardson  }
776d55085da49da8b7981494ea53ad23a6038fbb5c9Bill Richardson
77717f8d341099120da78a6ca71165834eefb0960edRandall Spangler#endif // FOR_LIBRARY
778