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