Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(22)

Unified Diff: src/platform/vboot_reference/utility/gbb_utility.cc

Issue 2549001: Refine gbb_utility for better maintainance (Closed) Base URL: ssh://gitrw.chromium.org/chromiumos
Patch Set: fix lint errors (extra space) Created 10 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | src/platform/vboot_reference/utility/include/gbb_utility.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/platform/vboot_reference/utility/gbb_utility.cc
diff --git a/src/platform/vboot_reference/utility/gbb_utility.cc b/src/platform/vboot_reference/utility/gbb_utility.cc
index b0aab56cb7a32836a0bb26a7d8fd1fe8e132ce64..8b10787b4a96e20fe0dd2d71121a95105540aa5e 100644
--- a/src/platform/vboot_reference/utility/gbb_utility.cc
+++ b/src/platform/vboot_reference/utility/gbb_utility.cc
@@ -155,6 +155,13 @@ int GoogleBinaryBlockUtil::search_header_signatures(const string &image,
static bool check_property_range(uint32_t off, uint32_t sz,
uint32_t hdr_sz, uint32_t max_sz,
const char *prop_name, bool verbose) {
+ // for backward compatibility, we allow zero entry here.
+ if (off == 0 && sz == 0) {
+ if (verbose)
+ fprintf(stderr, " warning: property %s is EMPTY.\n", prop_name);
+ return true;
+ }
+
if (off + sz > max_sz) {
if (verbose)
fprintf(stderr, " error: property %s exceed GBB.\n", prop_name);
@@ -205,14 +212,20 @@ bool GoogleBinaryBlockUtil::load_gbb_header(const string &image, long offset,
return false;
}
- // verify location of properties
- if (!check_property_range(h.hwid_offset, h.hwid_size,
- h.header_size, block_size, "hwid", verbose) ||
- !check_property_range(h.rootkey_offset, h.rootkey_size,
- h.header_size, block_size, "rootkey", verbose) ||
- !check_property_range(h.bmpfv_offset, h.bmpfv_size,
- h.header_size, block_size, "bmpfv", verbose)) {
- return false;
+ // verify properties
+ for (int i = 0; i < PROP_RANGE; i++) {
+ uint32_t off, size;
+ const char *name;
+
+ if (!find_property(static_cast<PROPINDEX>(i),
+ &off, &size, &name)) {
+ assert(!"invalid property.");
+ return false;
+ }
+
+ if (!check_property_range(off, size,
+ h.header_size, block_size, name, verbose))
+ return false;
}
return true;
@@ -220,21 +233,28 @@ bool GoogleBinaryBlockUtil::load_gbb_header(const string &image, long offset,
bool GoogleBinaryBlockUtil::find_property(PROPINDEX i,
uint32_t *poffset,
- uint32_t *psize) const {
+ uint32_t *psize,
+ const char** pname) const {
switch (i) {
case PROP_HWID:
*poffset = header_.hwid_offset;
*psize = header_.hwid_size;
+ if (pname)
+ *pname = "hardware_id";
break;
case PROP_ROOTKEY:
*poffset = header_.rootkey_offset;
*psize = header_.rootkey_size;
+ if (pname)
+ *pname = "root_key";
break;
case PROP_BMPFV:
*poffset = header_.bmpfv_offset;
*psize = header_.bmpfv_size;
+ if (pname)
+ *pname = "bmp_fv";
break;
default:
@@ -248,10 +268,11 @@ bool GoogleBinaryBlockUtil::find_property(PROPINDEX i,
bool GoogleBinaryBlockUtil::set_property(PROPINDEX i, const string &value) {
uint32_t prop_size;
uint32_t prop_offset;
+ const char *prop_name;
assert(is_valid_gbb);
- if (!find_property(i, &prop_offset, &prop_size)) {
+ if (!find_property(i, &prop_offset, &prop_size, &prop_name)) {
if (verbose)
fprintf(stderr, " internal error: unknown property (%d).\n",
static_cast<int>(i));
@@ -260,16 +281,16 @@ bool GoogleBinaryBlockUtil::set_property(PROPINDEX i, const string &value) {
if (prop_size < value.size()) {
if (verbose)
- fprintf(stderr, " error: value size (%zu) exceed capacity (%u).\n",
- value.size(), prop_size);
+ fprintf(stderr, " error: value size (%zu) exceed property capacity "
+ "(%u): %s\n", value.size(), prop_size, prop_name);
return false;
}
if (i == PROP_HWID && prop_size == value.size()) {
// special case: this is NUL-terminated so it's better to keep one more \0
if (verbose)
- fprintf(stderr, "error: NUL-terminated string exceed capacity (%d)\n",
- prop_size);
+ fprintf(stderr, "error: NUL-terminated string exceed capacity (%d): %s\n",
+ prop_size, prop_name);
return false;
}
@@ -283,21 +304,45 @@ bool GoogleBinaryBlockUtil::set_property(PROPINDEX i, const string &value) {
string GoogleBinaryBlockUtil::get_property(PROPINDEX i) const {
uint32_t prop_size;
uint32_t prop_offset;
+ const char *prop_name;
assert(is_valid_gbb);
- if (!find_property(i, &prop_offset, &prop_size)) {
+ if (!find_property(i, &prop_offset, &prop_size, &prop_name)) {
if (verbose)
fprintf(stderr, " internal error: unknown property (%d).\n",
static_cast<int>(i));
return "";
}
+ // check range again to allow empty value (for compatbility)
+ if (prop_offset == 0 && prop_size == 0) {
+ if (verbose)
+ fprintf(stderr, " warning: empty property (%d): %s.\n",
+ static_cast<int>(i), prop_name);
+ return "";
+ }
+
string::const_iterator dest = file_content_.begin() +
header_offset_ + prop_offset;
return string(dest, dest + prop_size);
}
+string GoogleBinaryBlockUtil::get_property_name(PROPINDEX i) const {
+ uint32_t unused_off, unused_size;
+ const char *prop_name;
+
+ if (!find_property(i, &unused_off, &unused_size, &prop_name)) {
+ if (verbose)
+ fprintf(stderr, " internal error: unknown property (%d).\n",
+ static_cast<int>(i));
+ assert(!"invalid property index.");
+ return "";
+ }
+
+ return prop_name;
+}
+
bool GoogleBinaryBlockUtil::set_hwid(const char *hwid) {
return set_property(PROP_HWID, hwid);
}
@@ -310,31 +355,39 @@ bool GoogleBinaryBlockUtil::set_bmpfv(const string &value) {
return set_property(PROP_BMPFV, value);
}
-} // namespace vboot_reference
+} // namespace vboot_reference
#ifdef WITH_UTIL_MAIN
///////////////////////////////////////////////////////////////////////
// command line utilities
+#include <map>
+
+using vboot_reference::GoogleBinaryBlockUtil;
+
// utility function: provide usage of this utility and exit.
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\n"
- "-g, --get \tGet (read) from bios_file, "
+ "Usage: %s [-g|-s] [OPTIONS] bios_file [output_file]\n"
+ "\n"
+ "GET MODE:\n"
+ "-g, --get (default)\tGet (read) from bios_file, "
"with following options:\n"
" --hwid \tReport hardware id (default).\n"
" -k, --rootkey=FILE \tFile name to export Root Key.\n"
" -b, --bmpfv=FILE \tFile name to export Bitmap FV.\n"
"\n"
+ "SET MODE:\n"
"-s, --set \tSet (write) to bios_file, "
"with following options:\n"
+ " -o, --output=FILE \tNew file name for ouptput.\n"
" -i, --hwid=HWID \tThe new hardware id to be changed.\n"
" -k, --rootkey=FILE \tFile name of new Root Key.\n"
- " -b, --bmpfv=FILE \tFile name of new Bitmap FV\n"
+ " -b, --bmpfv=FILE \tFile name of new Bitmap FV.\n"
"\n"
- " SAMPLE:\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);
@@ -342,43 +395,63 @@ static void usagehelp_exit(const char *prog_name) {
}
// utility function: export a property from GBB to given file.
+// if filename was empty, export to console (screen).
// return true on success, otherwise false.
-static bool export_property_to_file(const string &filename,
- const char *name, const string &value) {
- assert(!filename.empty());
- const char *fn = filename.c_str();
+static bool export_property(GoogleBinaryBlockUtil::PROPINDEX idx,
+ const string &filename,
+ const GoogleBinaryBlockUtil &util) {
+ string prop_name = util.get_property_name(idx),
+ value = util.get_property(idx);
+ const char *name = prop_name.c_str();
+
+ if (filename.empty()) {
+ // write to console
+ printf("%s: %s\n", name, value.c_str());
+ } else {
+ const char *fn = filename.c_str();
- if (!write_nonempty_file(fn, value)) {
- fprintf(stderr, "error: failed to export %s to file: %s\n", name, fn);
- return false;
+ if (!write_nonempty_file(fn, value)) {
+ fprintf(stderr, "error: failed to export %s to file: %s\n", name, fn);
+ return false;
+ }
+ printf(" - exported %s to file: %s\n", name, fn);
}
- printf(" - exported %s to file: %s\n", name, fn);
return true;
}
-// utility function: import a property to GBB by given file.
+// utility function: import a property to GBB by given source (file or string).
// return true on success, otherwise false.
// is succesfully imported into GBB.
-static bool import_property_from_file(
- const string &filename, const char *name,
- bool (vboot_reference::GoogleBinaryBlockUtil::*setter)(const string &value),
- vboot_reference::GoogleBinaryBlockUtil *putil) {
- assert(!filename.empty());
-
- printf(" - import %s from %s: ", name, filename.c_str());
- string v = read_nonempty_file(filename.c_str());
- if (v.empty()) {
- printf("invalid file.\n");
- return false;
- }
-
- if (!(putil->*setter)(v)) {
- printf("invalid content.\n");
- return false;
+static bool import_property(
+ GoogleBinaryBlockUtil::PROPINDEX idx, const string &source,
+ bool source_as_file, GoogleBinaryBlockUtil *putil) {
+ assert(!source.empty());
+ string prop_name = putil->get_property_name(idx);
+
+ if (source_as_file) {
+ printf(" - import %s from %s: ", prop_name.c_str(), source.c_str());
+ string v = read_nonempty_file(source.c_str());
+ if (v.empty()) {
+ printf("invalid file.\n");
+ return false;
+ }
+ if (!putil->set_property(idx, v)) {
+ printf("invalid content.\n");
+ return false;
+ }
+ printf("success.\n");
+ } else {
+ // source as string
+ string old_value = putil->get_property(idx);
+ bool result = putil->set_property(idx, source);
+ printf(" - %s changed from '%s' to '%s': %s\n",
+ prop_name.c_str(), old_value.c_str(), source.c_str(),
+ result ? "success" : "failed");
+ if (!result)
+ return false;
}
- printf("success.\n");
return true;
}
@@ -389,29 +462,39 @@ int main(int argc, char *argv[]) {
const char *myname = argv[0];
int err_stage = 0; // an indicator for error exits
+ // small parameter helper class
+ class OptPropertyMap: public
+ std::map<GoogleBinaryBlockUtil::PROPINDEX, string> {
+ public:
+ bool set_new_value(GoogleBinaryBlockUtil::PROPINDEX id, const string &v) {
+ if (find(id) != end())
+ return false;
+ (*this)[id] = v;
+ return true;
+ }
+ };
+ OptPropertyMap opt_props;
+
struct GBBUtilOptions {
bool get_mode, set_mode;
- bool use_hwid, use_rootkey, use_bmpfv;
- string hwid, rootkey_fn, bmpfv_fn;
+ string input_fn, output_fn;
} myopts;
-
myopts.get_mode = myopts.set_mode = false;
- myopts.use_hwid = myopts.use_rootkey = myopts.use_bmpfv = false;
// snippets for getopt_long
int option_index, opt;
static struct option long_options[] = {
- {"get", 0, NULL, 'g' },
- {"set", 0, NULL, 's' },
- {"hwid", 2, NULL, 'i' },
+ {"get", 0, NULL, 'g' },
+ {"set", 0, NULL, 's' },
+ {"output", 1, NULL, 'o' },
+ {"hwid", 2, NULL, 'i' },
{"rootkey", 1, NULL, 'k' },
- {"bmpfv", 1, NULL, 'b' },
- { NULL, 0, NULL, 0 },
+ {"bmpfv", 1, NULL, 'b' },
+ { NULL, 0, NULL, 0 },
};
- int opt_props = 0; // number of assigned properties.
// parse command line options
- while ((opt = getopt_long(argc, argv, "gsi:k:b:",
+ while ((opt = getopt_long(argc, argv, "gso:i:k:b:",
long_options, &option_index)) >= 0) {
switch (opt) {
case 'g':
@@ -422,23 +505,26 @@ int main(int argc, char *argv[]) {
myopts.set_mode = true;
break;
+ case 'o':
+ myopts.output_fn = optarg;
+ break;
+
case 'i':
- opt_props++;
- myopts.use_hwid = true;
- if (optarg)
- myopts.hwid = optarg;
+ if (!opt_props.set_new_value(
+ GoogleBinaryBlockUtil::PROP_HWID, optarg ? optarg : ""))
+ usagehelp_exit(myname);
break;
case 'k':
- opt_props++;
- myopts.use_rootkey = true;
- myopts.rootkey_fn = optarg;
+ if (!opt_props.set_new_value(
+ GoogleBinaryBlockUtil::PROP_ROOTKEY, optarg))
+ usagehelp_exit(myname);
break;
case 'b':
- opt_props++;
- myopts.use_bmpfv = true;
- myopts.bmpfv_fn = optarg;
+ if (!opt_props.set_new_value(
+ GoogleBinaryBlockUtil::PROP_BMPFV, optarg))
+ usagehelp_exit(myname);
break;
default:
@@ -450,25 +536,42 @@ int main(int argc, char *argv[]) {
argc -= optind;
argv += optind;
- // check parameters configuration
- if (!(argc == 1 || (myopts.set_mode && argc == 2)))
+ // adjust non-dashed parameters
+ if (myopts.output_fn.empty() && argc == 2) {
+ myopts.output_fn = argv[1];
+ argc--;
+ }
+
+ // currently, the only parameter is 'input file'.
+ if (argc == 1) {
+ myopts.input_fn = argv[0];
+ } else {
usagehelp_exit(myname);
+ }
- // stage: parameter parsing
+ // stage: complete parameter parsing and checking
err_stage++;
if (myopts.get_mode == myopts.set_mode) {
- printf("error: please assign either get or set mode.\n");
+ if (myopts.get_mode) {
+ printf("error: please assign either get or set mode.\n");
+ return err_stage;
+ } else {
+ // enter 'get' mode by default, if not assigned.
+ myopts.get_mode = true;
+ }
+ }
+ if (myopts.get_mode && !myopts.output_fn.empty()) {
+ printf("error: get-mode does not create output files.\n");
return err_stage;
}
// stage: load image files
err_stage++;
- vboot_reference::GoogleBinaryBlockUtil util;
- const char *input_filename = argv[0],
- *output_filename= (argc > 1) ? argv[1] : argv[0];
+ GoogleBinaryBlockUtil util;
- if (!util.load_from_file(input_filename)) {
- printf("error: cannot load valid BIOS file: %s\n", input_filename);
+ 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());
return err_stage;
}
@@ -476,53 +579,52 @@ int main(int argc, char *argv[]) {
err_stage++;
if (myopts.get_mode) {
// get mode
- if (opt_props < 1) // enable hwid by default
- myopts.use_hwid = true;
-
- if (myopts.use_hwid)
- printf("Hardware ID: %s\n", util.get_hwid().c_str());
- if (myopts.use_rootkey)
- export_property_to_file(myopts.rootkey_fn, "rootkey", util.get_rootkey());
- if (myopts.use_bmpfv)
- export_property_to_file(myopts.bmpfv_fn, "bmpfv", util.get_bmpfv());
+ if (opt_props.empty()) // enable hwid by default
+ opt_props.set_new_value(GoogleBinaryBlockUtil::PROP_HWID, "");
+
+ for (OptPropertyMap::const_iterator i = opt_props.begin();
+ i != opt_props.end();
+ i++) {
+ export_property(i->first, i->second, util);
+ }
+
} else {
// set mode
assert(myopts.set_mode);
- if (opt_props < 1) {
+
+ if (opt_props.empty()) {
printf("nothing to change. abort.\n");
return err_stage;
}
- // HWID does not come from file, so update it direcly here.
- if (myopts.use_hwid) {
- string old_hwid = util.get_hwid();
- if (!util.set_hwid(myopts.hwid.c_str())) {
- printf("error: inproper hardware id: %s\n",
- myopts.hwid.c_str());
+ for (OptPropertyMap::const_iterator i = opt_props.begin();
+ i != opt_props.end();
+ i++) {
+ bool source_as_file = true;
+
+ // the hwid command line parameter was a simple string.
+ if (i->first == GoogleBinaryBlockUtil::PROP_HWID)
+ source_as_file = false;
+
+ if (!import_property(i->first, i->second, source_as_file, &util)) {
+ printf("error: cannot set properties. abort.\n");
return err_stage;
}
- printf(" - Hardware id changed: %s -> %s.\n",
- old_hwid.c_str(), util.get_hwid().c_str());
- }
-
- // import other properties from file
- if ((myopts.use_rootkey &&
- !import_property_from_file(myopts.rootkey_fn, "rootkey",
- &vboot_reference::GoogleBinaryBlockUtil::set_rootkey, &util)) ||
- (myopts.use_bmpfv &&
- !import_property_from_file(myopts.bmpfv_fn, "bmpfv",
- &vboot_reference::GoogleBinaryBlockUtil::set_bmpfv, &util))) {
- printf("error: cannot set new properties. abort.\n");
- return err_stage;
}
// stage: write output
err_stage++;
- if (!util.save_to_file(output_filename)) {
- printf("error: cannot save to file: %s\n", output_filename);
+
+ // use input filename (overwrite) by default
+ if (myopts.output_fn.empty())
+ myopts.output_fn = myopts.input_fn;
+
+ assert(!myopts.output_fn.empty());
+ if (!util.save_to_file(myopts.output_fn.c_str())) {
+ printf("error: cannot save to file: %s\n", myopts.output_fn.c_str());
return err_stage;
} else {
- printf("successfully saved new image to: %s\n", output_filename);
+ printf("successfully saved new image to: %s\n", myopts.output_fn.c_str());
}
}
« no previous file with comments | « no previous file | src/platform/vboot_reference/utility/include/gbb_utility.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698