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()); |