diff options
author | Bill Richardson <wfrichar@chromium.org> | 2011-02-04 15:01:37 -0800 |
---|---|---|
committer | Bill Richardson <wfrichar@chromium.org> | 2011-02-04 15:01:37 -0800 |
commit | d55085da49da8b7981494ea53ad23a6038fbb5c9 (patch) | |
tree | e483d0964d164c3a87c88eef343fc4e3dae0fc1b | |
parent | 6b2b81c13081fc22865e1f5ae2ce5789c91b3ce0 (diff) | |
download | vboot-d55085da49da8b7981494ea53ad23a6038fbb5c9.tar.gz |
Slight modification to a previously-LGTM'd CL, to work with ebuild changes.
This replaces http://codereview.chromium.org/6307007. The only difference is
the Makefile. The vboot_reference ebuild has been changed so that we only
attempt to build bmpblk_utility on the host.
Change-Id: I4902703baba155e0d2d7646d19b233aa695c282f
BUG=chromium-os:11017,chromium-os:10599
TEST=none
No test needed. If buildbot is green, it's verified.
Review URL: http://codereview.chromium.org/6334111
-rw-r--r-- | firmware/include/bmpblk_header.h | 123 | ||||
-rw-r--r-- | firmware/version.c | 2 | ||||
-rw-r--r-- | utility/Makefile | 7 | ||||
-rw-r--r-- | utility/bmpblk_utility.cc | 551 | ||||
-rw-r--r-- | utility/include/bmpblk_utility.h | 112 |
5 files changed, 794 insertions, 1 deletions
diff --git a/firmware/include/bmpblk_header.h b/firmware/include/bmpblk_header.h new file mode 100644 index 00000000..3aa981ce --- /dev/null +++ b/firmware/include/bmpblk_header.h @@ -0,0 +1,123 @@ +/* Copyright (c) 2010 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Data structure definitions for firmware screen block (BMPBLOCK). + * + * The BmpBlock structure looks like: + * +-----------------------------------------+ + * | BmpBlock Header | + * +-----------------------------------------+ + * | ScreenLayout[0] | \ + * +-----------------------------------------+ | + * | ScreenLayout[1] | | + * +-----------------------------------------+ Localization[0] + * | ... | | + * +-----------------------------------------+ | + * | ScreenLayout[number_of_screenlayouts-1] | / + * +-----------------------------------------+ + * | ScreenLayout[0] | \ + * +-----------------------------------------+ Localization[1] + * | ... | / + * +-----------------------------------------+ ... + * | ScreenLayout[0] | \ + * +-----------------------------------------+ Localization[ + * | ... | / number_of_localizations-1] + * +-----------------------------------------+ + * | ImageInfo[0] | + * +-----------------------------------------+ + * | Image Content | + * +-----------------------------------------+ + * | ImageInfo[2] | ImageInfo is 4-byte aligned. + * +-----------------------------------------+ + * | Image Content | + * +-----------------------------------------+ + * | ... | + * +-----------------------------------------+ + * | ImageInfo[number_fo_images-1] | + * +-----------------------------------------+ + * | Image Content | + * +-----------------------------------------+ + * + */ + +#ifndef VBOOT_REFERENCE_BMPBLK_HEADER_H_ +#define VBOOT_REFERENCE_BMPBLK_HEADER_H_ + +#include "sysincludes.h" + +__pragma(pack(push, 1)) /* Support packing for MSVC. */ + +#define BMPBLOCK_SIGNATURE "$BMP" +#define BMPBLOCK_SIGNATURE_SIZE (4) + +#define BMPBLOCK_MAJOR_VERSION (0x0001) +#define BMPBLOCK_MINOR_VERSION (0x0000) + +#define MAX_IMAGE_IN_LAYOUT (8) + +/* BMPBLOCK header, describing how many screen layouts and image infos */ +typedef struct BmpBlockHeader { + uint8_t signature[BMPBLOCK_SIGNATURE_SIZE]; /* BMPBLOCK_SIGNATURE $BMP */ + uint16_t major_version; /* see BMPBLOCK_MAJOR_VER */ + uint16_t minor_version; /* see BMPBLOCK_MINOR_VER */ + uint32_t number_of_localizations; /* Number of localizations */ + uint32_t number_of_screenlayouts; /* Number of screen layouts in each + * localization */ + uint32_t number_of_imageinfos; /* Number of image infos */ + uint32_t reserved[3]; +} __attribute__((packed)) BmpBlockHeader; + +/* Screen layout, describing how to stack multiple images on screen */ +typedef struct ScreenLayout { + struct { + uint32_t x; /* X-offset of the image to be rendered */ + uint32_t y; /* Y-offset of the image to be rendered */ + uint32_t image_info_offset; /* Offset of image info from start of + * BMPBLOCK. 0 means end of it. */ + } images[MAX_IMAGE_IN_LAYOUT]; /* Images contained in the screen. Will be + * rendered from 0 to (number_of_images-1). */ +} __attribute__((packed)) ScreenLayout; + +/* Constants for screen index */ +typedef enum ScreenIndex { + SCREEN_DEVELOPER_MODE = 0, + SCREEN_RECOVERY_MODE, + SCREEN_RECOVERY_NO_OS, + SCREEN_RECOVERY_MISSING_OS, + MAX_SCREEN_INDEX, +} ScreenIndex; + +/* Image info, describing the information of the image block */ +typedef struct ImageInfo { + uint32_t tag; /* Tag it as a special image, like HWID */ + uint32_t width; /* Width of the image */ + uint32_t height; /* Height of the image */ + uint32_t format; /* File format of the image */ + uint32_t compression; /* Compression method to the image file */ + uint32_t original_size; /* Size of the original uncompressed image */ + uint32_t compressed_size; /* Size of the compressed image */ + uint32_t reserved; + /* NOTE: actual image content follows immediately */ +} __attribute__((packed)) ImageInfo; + +/* Constants for ImageInfo.tag */ +typedef enum ImageTag { + TAG_NONE = 0, + TAG_HWID, +} ImageTag; + +/* Constants for ImageInfo.format */ +typedef enum ImageFormat { + FORMAT_INVALID = 0, + FORMAT_BMP, +} ImageFormat; + +/* Constants for ImageInfo.compression */ +typedef enum Compression { + COMPRESS_NONE = 0, + COMPRESS_EFIv1, /* The x86 BIOS only supports this */ + COMPRESS_TBD, /* Only on ARM? */ +} Compression; + +#endif /* VBOOT_REFERENCE_BMPBLK_HEADER_H_ */ diff --git a/firmware/version.c b/firmware/version.c index e3073952..3776bc8b 100644 --- a/firmware/version.c +++ b/firmware/version.c @@ -1 +1 @@ -char* VbootVersion = "VBOOv=9e0713db"; +char* VbootVersion = "VBOOv=0a42e63b"; diff --git a/utility/Makefile b/utility/Makefile index 75b8f3d2..973d7855 100644 --- a/utility/Makefile +++ b/utility/Makefile @@ -36,6 +36,10 @@ TARGET_NAMES = dumpRSAPublicKey \ dev_debug_vboot \ pack_firmware_image +ifeq ($(MINIMAL),) +TARGET_NAMES += bmpblk_utility +endif + TARGET_BINS = $(addprefix ${BUILD_ROOT}/,$(TARGET_NAMES)) ALL_DEPS = $(addsuffix .d,${TARGET_BINS}) @@ -50,6 +54,9 @@ ${BUILD_ROOT}/dump_kernel_config: dump_kernel_config.c $(LIBS) ${BUILD_ROOT}/gbb_utility: gbb_utility.cc $(CXX) -DWITH_UTIL_MAIN $(CFLAGS) $< -o $@ +${BUILD_ROOT}/bmpblk_utility: bmpblk_utility.cc + $(CXX) -DWITH_UTIL_MAIN -lyaml $(CFLAGS) $< -o $@ + ${BUILD_ROOT}/load_kernel_test: load_kernel_test.c $(LIBS) $(CC) $(CFLAGS) $(INCLUDES) $< -o $@ $(LIBS) -lcrypto diff --git a/utility/bmpblk_utility.cc b/utility/bmpblk_utility.cc new file mode 100644 index 00000000..8da3e18f --- /dev/null +++ b/utility/bmpblk_utility.cc @@ -0,0 +1,551 @@ +// Copyright (c) 2010 The Chromium OS Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Utility for manipulating firmware screen block (BMPBLOCK) in GBB. +// + +#include "bmpblk_utility.h" + +#include <assert.h> +#include <errno.h> +#include <getopt.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <yaml.h> + +/* The offsets of width and height fields in a BMP file. + * See http://en.wikipedia.org/wiki/BMP_file_format */ +#define BMP_WIDTH_OFFSET 18 +#define BMP_HEIGHT_OFFSET 22 + +static void error(const char *format, ...) { + va_list ap; + va_start(ap, format); + fprintf(stderr, "ERROR: "); + vfprintf(stderr, format, ap); + va_end(ap); + exit(1); +} + +/////////////////////////////////////////////////////////////////////// +// BmpBlock Utility implementation + +namespace vboot_reference { + +BmpBlockUtil::BmpBlockUtil() { + initialize(); +} + +BmpBlockUtil::~BmpBlockUtil() { +} + +void BmpBlockUtil::initialize() { + config_.config_filename.clear(); + memset(&config_.header, '\0', BMPBLOCK_SIGNATURE_SIZE); + config_.images_map.clear(); + config_.screens_map.clear(); + config_.localizations.clear(); + bmpblock_.clear(); +} + +void BmpBlockUtil::load_from_config(const char *filename) { + load_yaml_config(filename); + fill_bmpblock_header(); + load_all_image_files(); + fill_all_image_infos(); +} + +void BmpBlockUtil::load_yaml_config(const char *filename) { + yaml_parser_t parser; + + config_.config_filename = filename; + config_.images_map.clear(); + config_.screens_map.clear(); + config_.localizations.clear(); + + FILE *fp = fopen(filename, "rb"); + if (!fp) { + perror(filename); + exit(errno); + } + + yaml_parser_initialize(&parser); + yaml_parser_set_input_file(&parser, fp); + parse_config(&parser); + yaml_parser_delete(&parser); + fclose(fp); +} + +void BmpBlockUtil::expect_event(yaml_parser_t *parser, + const yaml_event_type_e type) { + yaml_event_t event; + yaml_parser_parse(parser, &event); + if (event.type != type) { + error("Syntax error.\n"); + } + yaml_event_delete(&event); +} + +void BmpBlockUtil::parse_config(yaml_parser_t *parser) { + expect_event(parser, YAML_STREAM_START_EVENT); + expect_event(parser, YAML_DOCUMENT_START_EVENT); + parse_first_layer(parser); + expect_event(parser, YAML_DOCUMENT_END_EVENT); + expect_event(parser, YAML_STREAM_END_EVENT); +} + +void BmpBlockUtil::parse_first_layer(yaml_parser_t *parser) { + yaml_event_t event; + string keyword; + expect_event(parser, YAML_MAPPING_START_EVENT); + for (;;) { + yaml_parser_parse(parser, &event); + switch (event.type) { + case YAML_SCALAR_EVENT: + keyword = (char*)event.data.scalar.value; + if (keyword == "bmpblock") { + parse_bmpblock(parser); + } else if (keyword == "images") { + parse_images(parser); + } else if (keyword == "screens") { + parse_screens(parser); + } else if (keyword == "localizations") { + parse_localizations(parser); + } + break; + case YAML_MAPPING_END_EVENT: + yaml_event_delete(&event); + return; + default: + error("Syntax error in parsing config file.\n"); + } + yaml_event_delete(&event); + } +} + +void BmpBlockUtil::parse_bmpblock(yaml_parser_t *parser) { + yaml_event_t event; + yaml_parser_parse(parser, &event); + if (event.type != YAML_SCALAR_EVENT) { + error("Syntax error in parsing bmpblock.\n"); + } + config_.header.major_version = atoi((char*)event.data.scalar.value); + config_.header.minor_version = atoi( + strchr((char*)event.data.scalar.value, '.') + 1); + yaml_event_delete(&event); +} + +void BmpBlockUtil::parse_images(yaml_parser_t *parser) { + yaml_event_t event; + string image_name, image_filename; + expect_event(parser, YAML_MAPPING_START_EVENT); + for (;;) { + yaml_parser_parse(parser, &event); + switch (event.type) { + case YAML_SCALAR_EVENT: + image_name = (char*)event.data.scalar.value; + yaml_event_delete(&event); + yaml_parser_parse(parser, &event); + if (event.type != YAML_SCALAR_EVENT) { + error("Syntax error in parsing images.\n"); + } + image_filename = (char*)event.data.scalar.value; + config_.images_map[image_name] = ImageConfig(); + config_.images_map[image_name].filename = image_filename; + break; + case YAML_MAPPING_END_EVENT: + yaml_event_delete(&event); + return; + default: + error("Syntax error in parsing images.\n"); + } + yaml_event_delete(&event); + } +} + +void BmpBlockUtil::parse_layout(yaml_parser_t *parser, ScreenConfig &screen) { + yaml_event_t event; + string screen_name; + int depth = 0, index1 = 0, index2 = 0; + expect_event(parser, YAML_SEQUENCE_START_EVENT); + for (;;) { + yaml_parser_parse(parser, &event); + switch (event.type) { + case YAML_SEQUENCE_START_EVENT: + depth++; + break; + case YAML_SCALAR_EVENT: + switch (index2) { + case 0: + screen.data.images[index1].x = atoi((char*)event.data.scalar.value); + break; + case 1: + screen.data.images[index1].y = atoi((char*)event.data.scalar.value); + break; + case 2: + screen.image_names[index1] = (char*)event.data.scalar.value; + break; + default: + error("Syntax error in parsing layout.\n"); + } + index2++; + break; + case YAML_SEQUENCE_END_EVENT: + if (depth == 1) { + index1++; + index2 = 0; + } else if (depth == 0) { + yaml_event_delete(&event); + return; + } + depth--; + break; + default: + error("Syntax error in paring layout.\n"); + } + yaml_event_delete(&event); + } +} + +void BmpBlockUtil::parse_screens(yaml_parser_t *parser) { + yaml_event_t event; + string screen_name; + expect_event(parser, YAML_MAPPING_START_EVENT); + for (;;) { + yaml_parser_parse(parser, &event); + switch (event.type) { + case YAML_SCALAR_EVENT: + screen_name = (char*)event.data.scalar.value; + config_.screens_map[screen_name] = ScreenConfig(); + parse_layout(parser, config_.screens_map[screen_name]); + break; + case YAML_MAPPING_END_EVENT: + yaml_event_delete(&event); + return; + default: + error("Syntax error in parsing screens.\n"); + } + yaml_event_delete(&event); + } +} + +void BmpBlockUtil::parse_localizations(yaml_parser_t *parser) { + yaml_event_t event; + int depth = 0, index = 0; + expect_event(parser, YAML_SEQUENCE_START_EVENT); + for (;;) { + yaml_parser_parse(parser, &event); + switch (event.type) { + case YAML_SEQUENCE_START_EVENT: + config_.localizations.push_back(vector<string>()); + depth++; + break; + case YAML_SCALAR_EVENT: + config_.localizations[index].push_back((char*)event.data.scalar.value); + break; + case YAML_SEQUENCE_END_EVENT: + if (depth == 1) { + index++; + } else if (depth == 0) { + yaml_event_delete(&event); + return; + } + depth--; + break; + default: + error("Syntax error in parsing localizations.\n"); + } + yaml_event_delete(&event); + } +} + +void BmpBlockUtil::load_all_image_files() { + for (StrImageConfigMap::iterator it = config_.images_map.begin(); + it != config_.images_map.end(); + ++it) { + const string &content = read_image_file(it->second.filename.c_str()); + it->second.raw_content = content; + it->second.data.original_size = content.size(); + /* Use no compression as default */ + it->second.data.compression = COMPRESS_NONE; + it->second.compressed_content = content; + it->second.data.compressed_size = content.size(); + } +} + +const string BmpBlockUtil::read_image_file(const char *filename) { + string content; + vector<char> buffer; + + FILE *fp = fopen(filename, "rb"); + if (!fp) { + perror(filename); + exit(errno); + } + + if (fseek(fp, 0, SEEK_END) == 0) { + buffer.resize(ftell(fp)); + rewind(fp); + } + + if (!buffer.empty()) { + if(fread(&buffer[0], buffer.size(), 1, fp) != 1) { + perror(filename); + buffer.clear(); + } else { + content.assign(buffer.begin(), buffer.end()); + } + } + + fclose(fp); + return content; +} + +ImageFormat BmpBlockUtil::get_image_format(const string content) { + if (content[0] == 'B' && content[1] == 'M') + return FORMAT_BMP; + else + return FORMAT_INVALID; +} + +uint32_t BmpBlockUtil::get_bmp_image_width(const string content) { + const char *start = content.c_str(); + uint32_t width = *(uint32_t*)(start + BMP_WIDTH_OFFSET); + /* Do a rough verification. */ + assert(width > 0 && width < 1600); + return width; +} + +uint32_t BmpBlockUtil::get_bmp_image_height(const string content) { + const char *start = content.c_str(); + uint32_t height = *(uint32_t*)(start + BMP_HEIGHT_OFFSET); + /* Do a rough verification. */ + assert(height > 0 && height < 1000); + return height; +} + +void BmpBlockUtil::fill_all_image_infos() { + for (StrImageConfigMap::iterator it = config_.images_map.begin(); + it != config_.images_map.end(); + ++it) { + it->second.data.format = (uint32_t)get_image_format(it->second.raw_content); + switch (it->second.data.format) { + case FORMAT_BMP: + it->second.data.width = get_bmp_image_width(it->second.raw_content); + it->second.data.height = get_bmp_image_height(it->second.raw_content); + break; + default: + error("Unsupported image format."); + } + } +} + +void BmpBlockUtil::compress_all_images(const Compression compress) { + switch (compress) { + case COMPRESS_NONE: + for (StrImageConfigMap::iterator it = config_.images_map.begin(); + it != config_.images_map.end(); + ++it) { + it->second.data.compression = compress; + it->second.compressed_content = it->second.raw_content; + it->second.data.compressed_size = it->second.compressed_content.size(); + } + break; + default: + error("Unsupported data compression."); + } +} + +void BmpBlockUtil::fill_bmpblock_header() { + memset(&config_.header, '\0', sizeof(config_.header)); + memcpy(&config_.header.signature, BMPBLOCK_SIGNATURE, + BMPBLOCK_SIGNATURE_SIZE); + config_.header.number_of_localizations = config_.localizations.size(); + config_.header.number_of_screenlayouts = config_.localizations[0].size(); + for (unsigned int i = 1; i < config_.localizations.size(); ++i) { + assert(config_.header.number_of_screenlayouts == + config_.localizations[i].size()); + } + config_.header.number_of_imageinfos = config_.images_map.size(); +} + +void BmpBlockUtil::pack_bmpblock() { + bmpblock_.clear(); + + /* Compute the ImageInfo offsets from start of BMPBLOCK. */ + uint32_t current_offset = sizeof(BmpBlockHeader) + + sizeof(ScreenLayout) * config_.images_map.size(); + for (StrImageConfigMap::iterator it = config_.images_map.begin(); + it != config_.images_map.end(); + ++it) { + it->second.offset = current_offset; + current_offset += sizeof(ImageInfo) + it->second.data.compressed_size; + /* Make it 4-byte aligned. */ + if ((current_offset & 3) > 0) { + current_offset = (current_offset & ~3) + 4; + } + } + bmpblock_.resize(current_offset); + + /* Fill BmpBlockHeader struct. */ + string::iterator current_filled = bmpblock_.begin(); + std::copy(reinterpret_cast<char*>(&config_.header), + reinterpret_cast<char*>(&config_.header + 1), + current_filled); + current_filled += sizeof(config_.header); + + /* Fill all ScreenLayout structs. */ + for (unsigned int i = 0; i < config_.localizations.size(); ++i) { + for (unsigned int j = 0; j < config_.localizations[i].size(); ++j) { + ScreenConfig &screen = config_.screens_map[config_.localizations[i][j]]; + for (unsigned int k = 0; + k < MAX_IMAGE_IN_LAYOUT && !screen.image_names[k].empty(); + ++k) { + screen.data.images[k].image_info_offset = + config_.images_map[screen.image_names[k]].offset; + } + std::copy(reinterpret_cast<char*>(&screen.data), + reinterpret_cast<char*>(&screen.data + 1), + current_filled); + current_filled += sizeof(screen.data); + } + } + + /* Fill all ImageInfo structs and image contents. */ + for (StrImageConfigMap::iterator it = config_.images_map.begin(); + it != config_.images_map.end(); + ++it) { + current_filled = bmpblock_.begin() + it->second.offset; + std::copy(reinterpret_cast<char*>(&it->second.data), + reinterpret_cast<char*>(&it->second.data + 1), + current_filled); + current_filled += sizeof(it->second.data); + std::copy(it->second.compressed_content.begin(), + it->second.compressed_content.end(), + current_filled); + } +} + +void BmpBlockUtil::write_to_bmpblock(const char *filename) { + assert(!bmpblock_.empty()); + + FILE *fp = fopen(filename, "wb"); + if (!fp) { + perror(filename); + exit(errno); + } + + int r = fwrite(bmpblock_.c_str(), bmpblock_.size(), 1, fp); + fclose(fp); + if (r != 1) { + perror(filename); + exit(errno); + } +} + +} // namespace vboot_reference + +#ifdef WITH_UTIL_MAIN + +/////////////////////////////////////////////////////////////////////// +// Command line utilities + +using vboot_reference::BmpBlockUtil; + +// utility function: provide usage of this utility and exit. +static void usagehelp_exit(const char *prog_name) { + printf( + "Utility to manage firmware screen block (BMPBLOCK)\n" + "Usage: %s -c|-l|-x [options] BMPBLOCK_FILE\n" + "\n" + "Main Operation Mode:\n" + " -c, --create Create a new BMPBLOCK file. Should specify --config.\n" + " -l, --list List the contents of a BMPBLOCK file.\n" + " -x, --extract Extract embedded images and config file from a BMPBLOCK\n" + " file.\n" + "\n" + "Other Options:\n" + " -C, --config=CONFIG_FILE Config file describing screen layouts and\n" + " embedded images. (default: bmpblk.cfg)\n" + "\n" + "Example:\n" + " %s --create --config=screens.cfg bmpblk.bin\n" + , prog_name, prog_name); + exit(1); +} + +/////////////////////////////////////////////////////////////////////// +// main + +int main(int argc, char *argv[]) { + const char *prog_name = argv[0]; + BmpBlockUtil util; + + struct BmpBlockUtilOptions { + bool create_mode, list_mode, extract_mode; + string config_fn, bmpblock_fn; + } options; + + int longindex, opt; + static struct option longopts[] = { + {"create", 0, NULL, 'c'}, + {"list", 0, NULL, 'l'}, + {"extract", 0, NULL, 'x'}, + {"config", 1, NULL, 'C'}, + { NULL, 0, NULL, 0 }, + }; + + while ((opt = getopt_long(argc, argv, "clxC:", longopts, &longindex)) >= 0) { + switch (opt) { + case 'c': + options.create_mode = true; + break; + case 'l': + options.list_mode = true; + break; + case 'x': + options.extract_mode = true; + break; + case 'C': + options.config_fn = optarg; + break; + default: + case '?': + usagehelp_exit(prog_name); + break; + } + } + argc -= optind; + argv += optind; + + if (argc == 1) { + options.bmpblock_fn = argv[0]; + } else { + usagehelp_exit(prog_name); + } + + if (options.create_mode) { + util.load_from_config(options.config_fn.c_str()); + util.pack_bmpblock(); + util.write_to_bmpblock(options.bmpblock_fn.c_str()); + printf("The BMPBLOCK is sucessfully created in: %s.\n", + options.bmpblock_fn.c_str()); + } + + if (options.list_mode) { + /* TODO(waihong): Implement the list mode. */ + error("List mode hasn't been implemented yet.\n"); + } + + if (options.extract_mode) { + /* TODO(waihong): Implement the extract mode. */ + error("Extract mode hasn't been implemented yet.\n"); + } + + return 0; +} + +#endif // WITH_UTIL_MAIN diff --git a/utility/include/bmpblk_utility.h b/utility/include/bmpblk_utility.h new file mode 100644 index 00000000..b73b6630 --- /dev/null +++ b/utility/include/bmpblk_utility.h @@ -0,0 +1,112 @@ +// Copyright (c) 2010 The Chromium OS Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +#ifndef VBOOT_REFERENCE_BMPBLK_UTILITY_H_ +#define VBOOT_REFERENCE_BMPBLK_UTILITY_H_ + +#include "bmpblk_header.h" + +#include <yaml.h> + +#include <map> +#include <string> +#include <vector> + +using std::map; +using std::string; +using std::vector; + +namespace vboot_reference { + +/* Internal struct for contructing ImageInfo. */ +typedef struct ImageConfig { + ImageInfo data; + string filename; + string raw_content; + string compressed_content; + uint32_t offset; +} ImageConfig; + +/* Internal struct for contructing ScreenLayout. */ +typedef struct ScreenConfig { + ScreenLayout data; + string image_names[MAX_IMAGE_IN_LAYOUT]; +} ScreenConfig; + +typedef map<string, ImageConfig> StrImageConfigMap; +typedef map<string, ScreenConfig> StrScreenConfigMap; + +/* Internal struct for contructing the whole BmpBlock. */ +typedef struct BmpBlockConfig { + string config_filename; + BmpBlockHeader header; + StrImageConfigMap images_map; + StrScreenConfigMap screens_map; + vector<vector<string> > localizations; +} BmpBlockConfig; + +class BmpBlockUtil { + public: + BmpBlockUtil(); + ~BmpBlockUtil(); + + /* Load all the images and related infomations according to a config file. */ + void load_from_config(const char *filename); + + /* Compress all the images using a given comression method. */ + void compress_all_images(const Compression compress); + + /* Contruct the bmpblock. */ + void pack_bmpblock(); + + /* Write the bmpblock to a file */ + void write_to_bmpblock(const char *filename); + + private: + /* Clear all internal data. */ + void initialize(); + + /* Elemental function called from load_from_config. + * Load the config file (yaml format) and parse it. */ + void load_yaml_config(const char *filename); + + /* Elemental function called from load_from_config. + * Load all image files into the internal variables. */ + void load_all_image_files(); + + /* Elemental function called from load_from_config. + * Contruct all ImageInfo structs. */ + void fill_all_image_infos(); + + /* Elemental function called from load_from_config. + * Contruct the BmpBlockHeader struct. */ + void fill_bmpblock_header(); + + /* Helper functions for parsing a YAML config file. */ + void expect_event(yaml_parser_t *parser, const yaml_event_type_e type); + void parse_config(yaml_parser_t *parser); + void parse_first_layer(yaml_parser_t *parser); + void parse_bmpblock(yaml_parser_t *parser); + void parse_images(yaml_parser_t *parser); + void parse_layout(yaml_parser_t *parser, ScreenConfig &screen); + void parse_screens(yaml_parser_t *parser); + void parse_localizations(yaml_parser_t *parser); + + /* Useful functions */ + const string read_image_file(const char *filename); + ImageFormat get_image_format(const string content); + uint32_t get_bmp_image_width(const string content); + uint32_t get_bmp_image_height(const string content); + + /* Internal variable for storing the config of BmpBlock. */ + BmpBlockConfig config_; + + /* Internal variable for storing the content of BmpBlock. */ + string bmpblock_; +}; + +} // namespace vboot_reference + +#endif // VBOOT_REFERENCE_BMPBLK_UTILITY_H_ |