summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHung-Te Lin <hungte@chromium.org>2011-08-26 15:13:45 +0800
committerHung-Te Lin <hungte@chromium.org>2011-08-29 16:22:09 -0700
commitfec47595ce655c580749f9a3f47e1fd6bd4d8ee3 (patch)
treeb11ffec3c040b57a0a0ffa4a107c7d15304ddae9
parentcce4171545faa02611c1db6ca1c554370385b012 (diff)
downloadvboot-fec47595ce655c580749f9a3f47e1fd6bd4d8ee3.tar.gz
gbb_utility: add --flags parameter.
The --flags is added to get/set the "flags" field. BUG=chrome-os-partner:2317 TEST=gbb_utiltiy --get --flags bios.bin # see flags as 0 gbb_utility --set --flags=0x3052 bios.bin # for version error message for GBB1.0 files, # and see flag value changed for GBB1.1+ files gbb_utility --get --flags bios.bin # flag as 0 for GBB1.0, 0x3052 for GBB1.1+ Change-Id: I7aab62c8fc32ea08b4822e496f543511ff5e5ebc Reviewed-on: http://gerrit.chromium.org/gerrit/6721 Reviewed-by: Bill Richardson <wfrichar@chromium.org> Reviewed-by: Randall Spangler <rspangler@chromium.org> Tested-by: Hung-Te Lin <hungte@chromium.org>
-rw-r--r--firmware/include/gbb_header.h8
-rw-r--r--utility/gbb_utility.cc167
-rw-r--r--utility/include/gbb_utility.h9
3 files changed, 156 insertions, 28 deletions
diff --git a/firmware/include/gbb_header.h b/firmware/include/gbb_header.h
index b9ac3e82..c9d2909c 100644
--- a/firmware/include/gbb_header.h
+++ b/firmware/include/gbb_header.h
@@ -46,7 +46,7 @@ typedef struct GoogleBinaryBlockHeader {
uint16_t major_version; /* See GBB_MAJOR_VER */
uint16_t minor_version; /* See GBB_MINOR_VER */
uint32_t header_size; /* size of GBB header in bytes */
- uint32_t reserved;
+ uint32_t flags; /* Flags (see GBB_FLAG_*), should be 0 for 1.0. */
uint32_t hwid_offset; /* HWID offset from start of header */
uint32_t hwid_size; /* HWID size in bytes */
@@ -57,11 +57,7 @@ typedef struct GoogleBinaryBlockHeader {
uint32_t recovery_key_offset; /* Recovery Key offset from start of header */
uint32_t recovery_key_size; /* Recovery Key size in bytes */
- /* Fields added in version 1.1 */
- uint32_t flags; /* Flags (see GBB_FLAG_*). Readers should return
- * flags=0 for v1.0 structs. */
-
- uint8_t pad[76]; /* To match GBB_HEADER_SIZE. Initialize to 0. */
+ uint8_t pad[80]; /* To match GBB_HEADER_SIZE. Initialize to 0. */
} __attribute__((packed)) GoogleBinaryBlockHeader;
#ifdef __cplusplus
diff --git a/utility/gbb_utility.cc b/utility/gbb_utility.cc
index a051589c..544e1848 100644
--- a/utility/gbb_utility.cc
+++ b/utility/gbb_utility.cc
@@ -73,6 +73,29 @@ static bool write_nonempty_file(const char *filename, const string &content) {
return r == 1;
}
+// utility function: convert integer to little-endian encoded bytes
+// return the byte array in string type
+static string int2bytes(const uint32_t value) {
+ const char *pvalue = reinterpret_cast<const char*>(&value);
+ return string(pvalue, sizeof(value));
+}
+
+// utility function: convert little-endian encoded bytes to integer
+// return value in uint32_t type
+static uint32_t bytes2int(const string &bytes) {
+ assert(bytes.size() == sizeof(uint32_t));
+ return *reinterpret_cast<const uint32_t*>(bytes.c_str());
+}
+
+// utility function: compare a GBB header with given version numbers.
+// return 1 for "larger", 0 for "equal" and -1 for "smaller".
+static int version_compare(const GoogleBinaryBlockHeader& header,
+ int major, int minor) {
+ if (header.major_version != major)
+ return header.major_version - major;
+ return header.minor_version - minor;
+}
+
///////////////////////////////////////////////////////////////////////
// GBB Utility implementation
@@ -277,6 +300,13 @@ bool GoogleBinaryBlockUtil::find_property(PROPINDEX i,
uint32_t *psize,
const char** pname) const {
switch (i) {
+ case PROP_FLAGS:
+ *poffset = (uint8_t*)&header_.flags - (uint8_t*)&header_;
+ *psize = sizeof(header_.flags);
+ if (pname)
+ *pname = "flags";
+ break;
+
case PROP_HWID:
*poffset = header_.hwid_offset;
*psize = header_.hwid_size;
@@ -327,19 +357,48 @@ bool GoogleBinaryBlockUtil::set_property(PROPINDEX i, const string &value) {
if (!find_property(i, &prop_offset, &prop_size, &prop_name))
return false;
+ // special processing by version
+ if (version_compare(header_, 1, 1) < 0) {
+ if (i == PROP_FLAGS) {
+ assert(value.size() == prop.size());
+ if (int2bytes(0) != value) {
+ if (verbose)
+ fprintf(stderr,
+ "error: property %s is not supported on GBB version %d.%d\n",
+ prop_name, header_.major_version, header_.minor_version);
+ return false;
+ }
+ }
+ }
+
+
+
if (prop_size < value.size()) {
if (verbose)
- fprintf(stderr, " error: value size (%zu) exceed property capacity "
+ 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): %s\n",
- prop_size, prop_name);
- return false;
+ // special properties
+ switch (i) {
+ case PROP_HWID:
+ if (value.size() == prop_size) {
+ if (verbose)
+ fprintf(stderr,
+ "error: NUL-terminated string exceed capacity (%d): %s\n",
+ prop_size, prop_name);
+ return false;
+ }
+ break;
+
+ case PROP_FLAGS:
+ assert(value.size() == prop_size);
+ header_.flags = bytes2int(value);
+ break;
+
+ default:
+ break;
}
string::iterator dest = file_content_.begin() + header_offset_ + prop_offset;
@@ -367,6 +426,12 @@ string GoogleBinaryBlockUtil::get_property(PROPINDEX i) const {
return "";
}
+ // special processing by version
+ if (version_compare(header_, 1, 1) < 0) {
+ if (i == PROP_FLAGS)
+ return int2bytes(0);
+ }
+
string::const_iterator dest = file_content_.begin() +
header_offset_ + prop_offset;
return string(dest, dest + prop_size);
@@ -384,6 +449,14 @@ string GoogleBinaryBlockUtil::get_property_name(PROPINDEX i) const {
return prop_name;
}
+uint32_t GoogleBinaryBlockUtil::get_flags() const {
+ return bytes2int(get_property(PROP_FLAGS));
+}
+
+bool GoogleBinaryBlockUtil::set_flags(const uint32_t flags) {
+ return set_property(PROP_FLAGS, int2bytes(flags));
+}
+
bool GoogleBinaryBlockUtil::set_hwid(const char *hwid) {
return set_property(PROP_HWID, hwid);
}
@@ -413,7 +486,7 @@ using vboot_reference::GoogleBinaryBlockUtil;
// utility function: provide usage of this utility and exit.
static void usagehelp_exit(const char *prog_name) {
- printf(
+ fprintf(stderr,
"Utility to manage Google Binary Block (GBB)\n"
"Usage: %s [-g|-s|-c] [OPTIONS] bios_file [output_file]\n"
"\n"
@@ -421,6 +494,7 @@ static void usagehelp_exit(const char *prog_name) {
"-g, --get (default)\tGet (read) from bios_file, "
"with following options:\n"
" --hwid \tReport hardware id (default).\n"
+ " --flags \tReport header flags.\n"
" -k, --rootkey=FILE \tFile name to export Root Key.\n"
" -b, --bmpfv=FILE \tFile name to export Bitmap FV.\n"
" --recoverykey=FILE\tFile name to export Recovery Key.\n"
@@ -430,6 +504,7 @@ static void usagehelp_exit(const char *prog_name) {
"with following options:\n"
" -o, --output=FILE \tNew file name for ouptput.\n"
" -i, --hwid=HWID \tThe new hardware id to be changed.\n"
+ " --flags=FLAGS \tThe new (numeric) flags value.\n"
" -k, --rootkey=FILE \tFile name of new Root Key.\n"
" -b, --bmpfv=FILE \tFile name of new Bitmap FV.\n"
" --recoverykey=FILE\tFile name of new Recovery Key.\n"
@@ -440,8 +515,8 @@ static void usagehelp_exit(const char *prog_name) {
"SAMPLE:\n"
" %s -g bios.bin\n"
" %s --set --hwid='New Model' -k key.bin bios.bin newbios.bin\n"
- " %s -c 0x100,0x1000,0x03DE80,0x1000 gbb.blob\n"
- , prog_name, 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);
}
@@ -457,7 +532,10 @@ static bool export_property(GoogleBinaryBlockUtil::PROPINDEX idx,
if (filename.empty()) {
// write to console
- printf("%s: %s\n", name, value.c_str());
+ if (idx == GoogleBinaryBlockUtil::PROP_FLAGS)
+ printf("%s: 0x%08x\n", name, bytes2int(value));
+ else
+ printf("%s: %s\n", name, value.c_str());
} else {
const char *fn = filename.c_str();
@@ -496,9 +574,14 @@ static bool import_property(
// 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 (idx == GoogleBinaryBlockUtil::PROP_FLAGS)
+ printf(" - %s changed from 0x%08x to 0x%08x: %s\n",
+ prop_name.c_str(), bytes2int(old_value), bytes2int(source),
+ result ? "success" : "failed");
+ else
+ 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;
}
@@ -521,7 +604,6 @@ static bool parse_creation_param(const string &input_string,
return false;
output_vector->push_back(param);
input = parsed + 1;
- // printf("(debug) param: %zd\n", param);
} while (*input);
return true;
@@ -567,6 +649,7 @@ int main(int argc, char *argv[]) {
{"rootkey", 1, NULL, 'k' },
{"bmpfv", 1, NULL, 'b' },
{"recoverykey", 1, NULL, 'R' },
+ {"flags", 2, NULL, 'L' },
{ NULL, 0, NULL, 0 },
};
@@ -586,7 +669,7 @@ int main(int argc, char *argv[]) {
myopts.create_mode = true;
assert(optarg);
if (!*optarg || !parse_creation_param(optarg, &myopts.create_param)) {
- printf("error: invalid creation parameter: %s\n", optarg);
+ fprintf(stderr, "error: invalid creation parameter: %s\n", optarg);
usagehelp_exit(myname);
}
break;
@@ -597,30 +680,61 @@ int main(int argc, char *argv[]) {
case 'i':
if (!opt_props.set_new_value(
- GoogleBinaryBlockUtil::PROP_HWID, optarg ? optarg : ""))
+ GoogleBinaryBlockUtil::PROP_HWID, optarg ? optarg : "")) {
+ fprintf(stderr, "error: cannot assign multiple HWID parameters\n");
usagehelp_exit(myname);
+ }
break;
case 'k':
if (!opt_props.set_new_value(
- GoogleBinaryBlockUtil::PROP_ROOTKEY, optarg))
+ GoogleBinaryBlockUtil::PROP_ROOTKEY, optarg)) {
+ fprintf(stderr, "error: cannot assign multiple rootkey parameters\n");
usagehelp_exit(myname);
+ }
break;
case 'b':
if (!opt_props.set_new_value(
- GoogleBinaryBlockUtil::PROP_BMPFV, optarg))
+ GoogleBinaryBlockUtil::PROP_BMPFV, optarg)) {
+ fprintf(stderr, "error: cannot assign multiple bmpfv parameters\n");
usagehelp_exit(myname);
+ }
break;
case 'R':
if (!opt_props.set_new_value(
- GoogleBinaryBlockUtil::PROP_RCVKEY, optarg))
+ GoogleBinaryBlockUtil::PROP_RCVKEY, optarg)) {
+ fprintf(stderr,
+ "error: cannot assign multiple recovery_key parameters\n");
usagehelp_exit(myname);
+ }
+ break;
+
+ case 'L':
+ {
+ uint32_t flags = 0;
+ char *endptr = optarg;
+
+ if (optarg) {
+ flags = strtoul(optarg, &endptr, 0);
+ if (endptr == optarg) {
+ fprintf(stderr, "error: invalid --flags value\n");
+ usagehelp_exit(myname);
+ }
+ }
+
+ if (!opt_props.set_new_value(GoogleBinaryBlockUtil::PROP_FLAGS,
+ optarg ? int2bytes(flags) : "")) {
+ fprintf(stderr, "error: cannot assign multiple flags parameters\n");
+ usagehelp_exit(myname);
+ }
+ }
break;
default:
case '?':
+ fprintf(stderr, "error: unknown param: %c\n", opt);
usagehelp_exit(myname);
break;
}
@@ -638,6 +752,7 @@ int main(int argc, char *argv[]) {
if (argc == 1) {
myopts.input_fn = argv[0];
} else {
+ fprintf(stderr, "error: unexpected parameters (%d)\n", argc);
usagehelp_exit(myname);
}
@@ -701,6 +816,13 @@ int main(int argc, char *argv[]) {
for (OptPropertyMap::const_iterator i = opt_props.begin();
i != opt_props.end();
i++) {
+ if (i->first == GoogleBinaryBlockUtil::PROP_HWID ||
+ i->first == GoogleBinaryBlockUtil::PROP_FLAGS) {
+ if (!i->second.empty()) {
+ printf("error: cannot assign value for --hwid/flags in --get.\n");
+ usagehelp_exit(myname);
+ }
+ }
export_property(i->first, i->second, util);
}
@@ -718,8 +840,9 @@ int main(int argc, char *argv[]) {
i++) {
bool source_as_file = true;
- // the hwid command line parameter was a simple string.
- if (i->first == GoogleBinaryBlockUtil::PROP_HWID)
+ // the hwid/flags are assigned in command line parameters
+ if (i->first == GoogleBinaryBlockUtil::PROP_HWID ||
+ i->first == GoogleBinaryBlockUtil::PROP_FLAGS)
source_as_file = false;
if (!import_property(i->first, i->second, source_as_file, &util)) {
diff --git a/utility/include/gbb_utility.h b/utility/include/gbb_utility.h
index 55d4a390..49d6d43a 100644
--- a/utility/include/gbb_utility.h
+++ b/utility/include/gbb_utility.h
@@ -16,6 +16,7 @@ class GoogleBinaryBlockUtil {
public:
// enumerate of available data fields
enum PROPINDEX {
+ PROP_FLAGS = -1,// flags (virtual property)
PROP_HWID, // hardware id
PROP_ROOTKEY, // root key
PROP_BMPFV, // bitmap FV
@@ -39,6 +40,14 @@ class GoogleBinaryBlockUtil {
// return true on success.
bool create_new(const std::vector<uint32_t> &create_param);
+ // retrieve the value of GBB header flags.
+ // return the flags value.
+ uint32_t get_flags() const;
+
+ // overwrite GBB header flags.
+ // return true on success.
+ bool set_flags(const uint32_t flags);
+
// retrieve the value of a property from GBB data.
// return the property value.
std::string get_property(PROPINDEX i) const;