Chromium Code Reviews| Index: utility/gbb_utility.cc |
| diff --git a/utility/gbb_utility.cc b/utility/gbb_utility.cc |
| index 83e9db6c5f6b0c0e9a9d9d3c7ea8689b6033862a..7d111ef34591abf61d9c9e8735730dfb33df86e5 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> |
| @@ -374,7 +375,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 +394,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,6 +466,59 @@ 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; |
| + |
| + 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; |
| +} |
| + |
| +static string create_new_gbb(const std::vector<uint32_t> &create_param) { |
|
Randall Spangler
2011/01/07 21:47:34
The current implementation of the GBB is done via
Hung-Te
2011/01/10 03:40:58
Done.
|
| + GoogleBinaryBlockHeader header = {0}; |
| + 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(); |
| + string blob; |
| + |
| + // max properties = available space in header / size of record (offset+size) |
| + size_t max_properties = |
| + (sizeof(header) - ((uint8_t*)prop - (uint8_t*)&header)) / |
| + (sizeof(uint32_t) * 2); |
| + |
| + if (create_param.size() >= max_properties) { |
| + printf("error: creation parameters cannot exceed %zu entries.\n", |
| + max_properties); |
| + return blob; |
| + } |
| + |
| + 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++; |
| + } |
| + |
| + blob.resize(allocated_size); |
| + std::copy((char*)&header, (char*)(&header + 1), blob.begin()); |
| + return blob; |
| +} |
| + |
| /////////////////////////////////////////////////////////////////////// |
| // main |
| @@ -483,8 +541,9 @@ 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; |
|
Che-Liang Chiou
2011/01/10 02:55:20
I'm not sure, but doesn't myopts.create_mode have
Hung-Te
2011/01/10 03:40:58
My bad. fixed.
|
| @@ -493,6 +552,7 @@ int main(int argc, char *argv[]) { |
| static struct option long_options[] = { |
| {"get", 0, NULL, 'g' }, |
| {"set", 0, NULL, 's' }, |
| + {"create", 0, NULL, 'c' }, |
| {"output", 1, NULL, 'o' }, |
| {"hwid", 2, NULL, 'i' }, |
| {"rootkey", 1, NULL, 'k' }, |
| @@ -502,7 +562,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 +573,17 @@ int main(int argc, char *argv[]) { |
| myopts.set_mode = true; |
| break; |
| + case 'c': |
| + myopts.create_mode = true; |
| + { |
| + const char *param = optarg ? optarg : "(empty)"; |
| + if (!parse_creation_param(param, myopts.create_param)) { |
|
Che-Liang Chiou
2011/01/10 02:55:20
Isn't this equivalent to "if (!optarg || !parse_cr
Hung-Te
2011/01/10 03:40:58
Because in that case I need to put something in er
|
| + printf("error: invalid creation parameter: %s\n", param); |
| + usagehelp_exit(myname); |
| + } |
| + } |
| + break; |
| + |
| case 'o': |
| myopts.output_fn = optarg; |
| break; |
| @@ -565,7 +636,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,6 +662,22 @@ int main(int argc, char *argv[]) { |
| return err_stage; |
| } |
| + if (myopts.create_mode) { |
| + // creation is not handled by GoogleBinaryBlockUtil. |
| + string blob = create_new_gbb(myopts.create_param); |
| + |
| + if (blob.empty()) |
| + return err_stage; |
| + |
| + if (!write_nonempty_file(myopts.output_fn.c_str(), blob)) { |
| + 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; |