| Index: utility/gbb_utility.cc
|
| diff --git a/utility/gbb_utility.cc b/utility/gbb_utility.cc
|
| index 83e9db6c5f6b0c0e9a9d9d3c7ea8689b6033862a..14f8ffeb59523122469d5f7b43222911440f3d7c 100644
|
| --- a/utility/gbb_utility.cc
|
| +++ b/utility/gbb_utility.cc
|
| @@ -10,6 +10,7 @@
|
| #include <assert.h>
|
| #include <getopt.h>
|
| #include <stdio.h>
|
| +#include <stdlib.h>
|
| #include <string.h>
|
|
|
| #include <string>
|
| @@ -93,6 +94,47 @@ void GoogleBinaryBlockUtil::initialize() {
|
| file_content_.clear();
|
| }
|
|
|
| +bool GoogleBinaryBlockUtil::create_new(
|
| + const std::vector<uint32_t> &create_param) {
|
| + uint32_t *prop = &header_.hwid_offset; // must be first entry.
|
| + uint32_t allocated_size = sizeof(header_);
|
| + std::vector<uint32_t>::const_iterator i = create_param.begin();
|
| +
|
| + // max properties = available space in header / size of record (offset+size)
|
| + size_t max_properties =
|
| + (sizeof(header_) - (reinterpret_cast<uint8_t*>(prop) -
|
| + reinterpret_cast<uint8_t*>(&header_))) /
|
| + (sizeof(uint32_t) * 2);
|
| +
|
| + if (create_param.size() >= max_properties) {
|
| + if (verbose)
|
| + fprintf(stderr, "error: creation parameters cannot exceed %zu entries.\n",
|
| + max_properties);
|
| + return false;
|
| + }
|
| +
|
| + initialize();
|
| + memcpy(header_.signature, GBB_SIGNATURE, GBB_SIGNATURE_SIZE);
|
| + header_.major_version = GBB_MAJOR_VER;
|
| + header_.minor_version = GBB_MINOR_VER;
|
| + header_.header_size = GBB_HEADER_SIZE;
|
| +
|
| + while (i != create_param.end()) {
|
| + *prop++ = allocated_size; // property offset
|
| + *prop++ = *i; // property size
|
| + allocated_size += *i;
|
| + i++;
|
| + }
|
| +
|
| + file_content_.resize(allocated_size);
|
| + std::copy(reinterpret_cast<char*>(&header_),
|
| + reinterpret_cast<char*>(&header_ + 1),
|
| + file_content_.begin());
|
| + is_valid_gbb = true;
|
| + return true;
|
| +}
|
| +
|
| +
|
| bool GoogleBinaryBlockUtil::load_from_file(const char *filename) {
|
| is_valid_gbb = false;
|
|
|
| @@ -374,7 +416,7 @@ using vboot_reference::GoogleBinaryBlockUtil;
|
| static void usagehelp_exit(const char *prog_name) {
|
| printf(
|
| "Utility to manage Google Binary Block (GBB)\n"
|
| - "Usage: %s [-g|-s] [OPTIONS] bios_file [output_file]\n"
|
| + "Usage: %s [-g|-s|-c] [OPTIONS] bios_file [output_file]\n"
|
| "\n"
|
| "GET MODE:\n"
|
| "-g, --get (default)\tGet (read) from bios_file, "
|
| @@ -393,10 +435,14 @@ static void usagehelp_exit(const char *prog_name) {
|
| " -b, --bmpfv=FILE \tFile name of new Bitmap FV.\n"
|
| " --recoverykey=FILE\tFile name of new Recovery Key.\n"
|
| "\n"
|
| + "CREATE MODE:\n"
|
| + "-c, --create=prop1_size,prop2_size...\n"
|
| + " \tCreate a GBB blob by given size list.\n"
|
| "SAMPLE:\n"
|
| " %s -g bios.bin\n"
|
| " %s --set --hwid='New Model' -k key.bin bios.bin newbios.bin\n"
|
| - , prog_name, prog_name, prog_name);
|
| + " %s -c 0x100,0x1000,0x03DE80,0x1000 gbb.blob\n"
|
| + , prog_name, prog_name, prog_name, prog_name);
|
| exit(1);
|
| }
|
|
|
| @@ -461,12 +507,34 @@ static bool import_property(
|
| return true;
|
| }
|
|
|
| +static bool parse_creation_param(const string &input_string,
|
| + std::vector<uint32_t> *output_vector) {
|
| + const char *input = input_string.c_str();
|
| + char *parsed = NULL;
|
| + uint32_t param;
|
| +
|
| + if (input_string.empty())
|
| + return false;
|
| +
|
| + do {
|
| + param = (uint32_t)strtol(input, &parsed, 0);
|
| + if (*parsed && *parsed != ',')
|
| + return false;
|
| + output_vector->push_back(param);
|
| + input = parsed + 1;
|
| + // printf("(debug) param: %zd\n", param);
|
| + } while (*input);
|
| +
|
| + return true;
|
| +}
|
| +
|
| ///////////////////////////////////////////////////////////////////////
|
| // main
|
|
|
| int main(int argc, char *argv[]) {
|
| const char *myname = argv[0];
|
| int err_stage = 0; // an indicator for error exits
|
| + GoogleBinaryBlockUtil util;
|
|
|
| // small parameter helper class
|
| class OptPropertyMap: public
|
| @@ -483,16 +551,18 @@ int main(int argc, char *argv[]) {
|
| OptPropertyMap opt_props;
|
|
|
| struct GBBUtilOptions {
|
| - bool get_mode, set_mode;
|
| + bool get_mode, set_mode, create_mode;
|
| string input_fn, output_fn;
|
| + std::vector<uint32_t> create_param;
|
| } myopts;
|
| - myopts.get_mode = myopts.set_mode = false;
|
| + myopts.get_mode = myopts.set_mode = myopts.create_mode = false;
|
|
|
| // snippets for getopt_long
|
| int option_index, opt;
|
| static struct option long_options[] = {
|
| {"get", 0, NULL, 'g' },
|
| {"set", 0, NULL, 's' },
|
| + {"create", 1, NULL, 'c' },
|
| {"output", 1, NULL, 'o' },
|
| {"hwid", 2, NULL, 'i' },
|
| {"rootkey", 1, NULL, 'k' },
|
| @@ -502,7 +572,7 @@ int main(int argc, char *argv[]) {
|
| };
|
|
|
| // parse command line options
|
| - while ((opt = getopt_long(argc, argv, "gso:i:k:b:",
|
| + while ((opt = getopt_long(argc, argv, "gsc:o:i:k:b:",
|
| long_options, &option_index)) >= 0) {
|
| switch (opt) {
|
| case 'g':
|
| @@ -513,6 +583,15 @@ int main(int argc, char *argv[]) {
|
| myopts.set_mode = true;
|
| break;
|
|
|
| + case 'c':
|
| + myopts.create_mode = true;
|
| + assert(optarg);
|
| + if (!*optarg || !parse_creation_param(optarg, &myopts.create_param)) {
|
| + printf("error: invalid creation parameter: %s\n", optarg);
|
| + usagehelp_exit(myname);
|
| + }
|
| + break;
|
| +
|
| case 'o':
|
| myopts.output_fn = optarg;
|
| break;
|
| @@ -565,7 +644,19 @@ int main(int argc, char *argv[]) {
|
|
|
| // stage: complete parameter parsing and checking
|
| err_stage++;
|
| - if (myopts.get_mode == myopts.set_mode) {
|
| + if (myopts.create_mode) {
|
| + if (myopts.get_mode || myopts.set_mode) {
|
| + printf("error: please assign only one mode from get/set/create.\n");
|
| + return err_stage;
|
| + }
|
| + if (!opt_props.empty() || myopts.create_param.empty()) {
|
| + printf("error: creation parameter syntax error.\n");
|
| + return err_stage;
|
| + }
|
| + if (myopts.output_fn.empty()) {
|
| + myopts.output_fn = myopts.input_fn;
|
| + }
|
| + } else if (myopts.get_mode == myopts.set_mode) {
|
| if (myopts.get_mode) {
|
| printf("error: please assign either get or set mode.\n");
|
| return err_stage;
|
| @@ -579,10 +670,22 @@ int main(int argc, char *argv[]) {
|
| return err_stage;
|
| }
|
|
|
| + if (myopts.create_mode) {
|
| + if (!util.create_new(myopts.create_param))
|
| + return err_stage;
|
| +
|
| + assert(!myopts.output_fn.empty());
|
| + if (!util.save_to_file(myopts.output_fn.c_str())) {
|
| + printf("error: cannot create to file: %s\n", myopts.output_fn.c_str());
|
| + return err_stage;
|
| + } else {
|
| + printf("successfully created new GBB to: %s\n", myopts.output_fn.c_str());
|
| + }
|
| + return 0;
|
| + }
|
| +
|
| // stage: load image files
|
| err_stage++;
|
| - GoogleBinaryBlockUtil util;
|
| -
|
| assert(!myopts.input_fn.empty());
|
| if (!util.load_from_file(myopts.input_fn.c_str())) {
|
| printf("error: cannot load valid BIOS file: %s\n", myopts.input_fn.c_str());
|
|
|