blob: 83e9db6c5f6b0c0e9a9d9d3c7ea8689b6033862a [file] [log] [blame]
Hung-Te Lin262668f2010-05-28 10:32:02 -07001// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4//
5// Utility for manipulating Google Binary Block (GBB)
6//
7
8#include "gbb_utility.h"
9
10#include <assert.h>
11#include <getopt.h>
12#include <stdio.h>
13#include <string.h>
14
15#include <string>
16#include <vector>
17#include <algorithm>
18
19using std::string;
20
21///////////////////////////////////////////////////////////////////////
22// Simple File Utilities
23
24// utility function: read a non-empty file.
25// return file content, or empty for any failure.
26static string read_nonempty_file(const char *filename) {
27 string file_content;
28 std::vector<char> buffer; // since image files are small, should be OK
29
30 FILE *fp = fopen(filename, "rb");
31 if (!fp) {
32 perror(filename);
33 return file_content;
34 }
35
36 // prepare buffer on successful seek
37 if (fseek(fp, 0, SEEK_END) == 0) {
38 buffer.resize(ftell(fp));
39 rewind(fp);
40 }
41
42 if (!buffer.empty()) {
43 if (fread(&buffer[0], buffer.size(), 1, fp) != 1) {
44 perror(filename);
45 buffer.clear(); // discard buffer when read fail.
46 } else {
47 file_content.assign(buffer.begin(), buffer.end());
48 }
49 }
50
51 fclose(fp);
52 return file_content;
53}
54
55// utility function: write non-empty content to file.
56// return true on success, otherwise false.
57static bool write_nonempty_file(const char *filename, const string &content) {
58 assert(!content.empty());
59
60 FILE *fp = fopen(filename, "wb");
61 if (!fp) {
62 perror(filename);
63 return false;
64 }
65
66 int r = fwrite(content.c_str(), content.size(), 1, fp);
67 fclose(fp);
68
69 if (r != 1)
70 perror(filename);
71
72 return r == 1;
73}
74
75///////////////////////////////////////////////////////////////////////
76// GBB Utility implementation
77
78namespace vboot_reference {
79
80GoogleBinaryBlockUtil::GoogleBinaryBlockUtil() {
81 assert(sizeof(header_) == GBB_HEADER_SIZE);
82 initialize();
83}
84
85GoogleBinaryBlockUtil::~GoogleBinaryBlockUtil() {
86}
87
88void GoogleBinaryBlockUtil::initialize() {
89 verbose = true;
90 is_valid_gbb = false;
91 header_offset_ = 0;
92 memset(&header_, 0, sizeof(header_));
93 file_content_.clear();
94}
95
96bool GoogleBinaryBlockUtil::load_from_file(const char *filename) {
97 is_valid_gbb = false;
98
99 file_content_ = read_nonempty_file(filename);
100 if (file_content_.empty())
101 return false;
102
103 switch (search_header_signatures(file_content_, &header_offset_)) {
104 case 0:
105 if (verbose)
106 fprintf(stderr, " error: cannot find any GBB signature.\n");
107 break;
108
109 case 1:
110 // fetch a copy of block header to check more detail
111 if (!load_gbb_header(file_content_, header_offset_, &header_)) {
112 if (verbose)
113 fprintf(stderr, " error: invalid GBB in image file.\n");
114 } else {
115 is_valid_gbb = true;
116 }
117 break;
118
119 default:
120 if (verbose)
121 fprintf(stderr, " error: found multiple GBB signatures.\n");
122 file_content_.clear();
123 break;
124 }
125
126 // discard if anything goes wrong
127 if (!is_valid_gbb)
128 initialize();
129
130 return is_valid_gbb;
131}
132
133bool GoogleBinaryBlockUtil::save_to_file(const char *filename) {
134 assert(is_valid_gbb && !file_content_.empty());
135 return write_nonempty_file(filename, file_content_);
136}
137
138int GoogleBinaryBlockUtil::search_header_signatures(const string &image,
139 long *poffset) const {
140 int found_signatures = 0;
141 size_t last_found_pos = 0;
142
143 while ((last_found_pos =
144 file_content_.find(GBB_SIGNATURE, last_found_pos, GBB_SIGNATURE_SIZE))
145 != file_content_.npos) {
146 *poffset = last_found_pos;
147 found_signatures++;
148 last_found_pos++; // for next iteration
149 }
150
151 return found_signatures;
152}
153
154// uility function for load_gbb_header to check property range
155static bool check_property_range(uint32_t off, uint32_t sz,
156 uint32_t hdr_sz, uint32_t max_sz,
157 const char *prop_name, bool verbose) {
Hung-Te Lin21ef1a32010-06-02 18:13:47 -0700158 // for backward compatibility, we allow zero entry here.
159 if (off == 0 && sz == 0) {
160 if (verbose)
161 fprintf(stderr, " warning: property %s is EMPTY.\n", prop_name);
162 return true;
163 }
164
Hung-Te Lin262668f2010-05-28 10:32:02 -0700165 if (off + sz > max_sz) {
166 if (verbose)
167 fprintf(stderr, " error: property %s exceed GBB.\n", prop_name);
168 return false;
169 }
170
171 if (off < hdr_sz) {
172 if (verbose)
173 fprintf(stderr, " error: property %s overlap GBB header.\n", prop_name);
174 return false;
175 }
176
177 return true;
178}
179
180bool GoogleBinaryBlockUtil::load_gbb_header(const string &image, long offset,
181 GoogleBinaryBlockHeader *phdr) const {
182 assert(phdr);
183
184 // check that GBB header does not extend past end of image
185 if (image.size() < (size_t)offset + GBB_HEADER_SIZE) {
186 if (verbose)
187 fprintf(stderr, " error: incomplete GBB.\n");
188 return false;
189 }
190
191 string::const_iterator block_ptr = image.begin() + offset;
192 size_t block_size = image.size() - offset;
193
194 std::copy(block_ptr, block_ptr + GBB_HEADER_SIZE,
195 reinterpret_cast<char*>(phdr));
196
197 const GoogleBinaryBlockHeader &h = *phdr; // for quick access
198
199 // check version
200 if (h.major_version != GBB_MAJOR_VER ||
201 h.minor_version != GBB_MINOR_VER) {
202 if (verbose)
203 fprintf(stderr, " error: invalid GBB version (%d.%d)\n",
204 h.major_version, h.minor_version);
205 return false;
206 }
207
208 if (h.header_size < GBB_HEADER_SIZE) {
209 if (verbose)
210 fprintf(stderr, " error: incompatible header size (%d < %d)\n",
211 h.header_size, GBB_HEADER_SIZE);
212 return false;
213 }
214
Hung-Te Lin21ef1a32010-06-02 18:13:47 -0700215 // verify properties
216 for (int i = 0; i < PROP_RANGE; i++) {
217 uint32_t off, size;
218 const char *name;
219
220 if (!find_property(static_cast<PROPINDEX>(i),
221 &off, &size, &name)) {
222 assert(!"invalid property.");
223 return false;
224 }
225
226 if (!check_property_range(off, size,
227 h.header_size, block_size, name, verbose))
228 return false;
Hung-Te Lin262668f2010-05-28 10:32:02 -0700229 }
230
231 return true;
232}
233
234bool GoogleBinaryBlockUtil::find_property(PROPINDEX i,
235 uint32_t *poffset,
Hung-Te Lin21ef1a32010-06-02 18:13:47 -0700236 uint32_t *psize,
237 const char** pname) const {
Hung-Te Lin262668f2010-05-28 10:32:02 -0700238 switch (i) {
239 case PROP_HWID:
240 *poffset = header_.hwid_offset;
241 *psize = header_.hwid_size;
Hung-Te Lin21ef1a32010-06-02 18:13:47 -0700242 if (pname)
243 *pname = "hardware_id";
Hung-Te Lin262668f2010-05-28 10:32:02 -0700244 break;
245
246 case PROP_ROOTKEY:
247 *poffset = header_.rootkey_offset;
248 *psize = header_.rootkey_size;
Hung-Te Lin21ef1a32010-06-02 18:13:47 -0700249 if (pname)
250 *pname = "root_key";
Hung-Te Lin262668f2010-05-28 10:32:02 -0700251 break;
252
253 case PROP_BMPFV:
254 *poffset = header_.bmpfv_offset;
255 *psize = header_.bmpfv_size;
Hung-Te Lin21ef1a32010-06-02 18:13:47 -0700256 if (pname)
257 *pname = "bmp_fv";
Hung-Te Lin262668f2010-05-28 10:32:02 -0700258 break;
259
Hung-Te Lin08dc5f32010-06-03 14:35:47 -0700260 case PROP_RCVKEY:
261 *poffset = header_.recovery_key_offset;;
262 *psize = header_.recovery_key_size;
263 if (pname)
264 *pname = "recovery_key";
265 break;
266
Hung-Te Lin262668f2010-05-28 10:32:02 -0700267 default:
Hung-Te Lin08dc5f32010-06-03 14:35:47 -0700268 if (verbose) {
269 fprintf(stderr, " internal error: unknown property (%d).\n",
270 static_cast<int>(i));
271 }
Hung-Te Lin262668f2010-05-28 10:32:02 -0700272 assert(!"invalid property index.");
273 return false;
274 }
275
276 return true;
277}
278
279bool GoogleBinaryBlockUtil::set_property(PROPINDEX i, const string &value) {
280 uint32_t prop_size;
281 uint32_t prop_offset;
Hung-Te Lin21ef1a32010-06-02 18:13:47 -0700282 const char *prop_name;
Hung-Te Lin262668f2010-05-28 10:32:02 -0700283
284 assert(is_valid_gbb);
285
Hung-Te Lin08dc5f32010-06-03 14:35:47 -0700286 if (!find_property(i, &prop_offset, &prop_size, &prop_name))
Hung-Te Lin262668f2010-05-28 10:32:02 -0700287 return false;
Hung-Te Lin262668f2010-05-28 10:32:02 -0700288
289 if (prop_size < value.size()) {
290 if (verbose)
Hung-Te Lin21ef1a32010-06-02 18:13:47 -0700291 fprintf(stderr, " error: value size (%zu) exceed property capacity "
292 "(%u): %s\n", value.size(), prop_size, prop_name);
Hung-Te Lin262668f2010-05-28 10:32:02 -0700293 return false;
294 }
295
296 if (i == PROP_HWID && prop_size == value.size()) {
297 // special case: this is NUL-terminated so it's better to keep one more \0
298 if (verbose)
Hung-Te Lin21ef1a32010-06-02 18:13:47 -0700299 fprintf(stderr, "error: NUL-terminated string exceed capacity (%d): %s\n",
300 prop_size, prop_name);
Hung-Te Lin262668f2010-05-28 10:32:02 -0700301 return false;
302 }
303
304 string::iterator dest = file_content_.begin() + header_offset_ + prop_offset;
305 file_content_.replace(dest, dest+prop_size, prop_size, '\0'); // wipe first
306 std::copy(value.begin(), value.end(), dest);
307
308 return true;
309}
310
311string GoogleBinaryBlockUtil::get_property(PROPINDEX i) const {
312 uint32_t prop_size;
313 uint32_t prop_offset;
Hung-Te Lin21ef1a32010-06-02 18:13:47 -0700314 const char *prop_name;
Hung-Te Lin262668f2010-05-28 10:32:02 -0700315
316 assert(is_valid_gbb);
317
Hung-Te Lin08dc5f32010-06-03 14:35:47 -0700318 if (!find_property(i, &prop_offset, &prop_size, &prop_name))
Hung-Te Lin262668f2010-05-28 10:32:02 -0700319 return "";
Hung-Te Lin262668f2010-05-28 10:32:02 -0700320
Hung-Te Lin21ef1a32010-06-02 18:13:47 -0700321 // check range again to allow empty value (for compatbility)
322 if (prop_offset == 0 && prop_size == 0) {
323 if (verbose)
324 fprintf(stderr, " warning: empty property (%d): %s.\n",
325 static_cast<int>(i), prop_name);
326 return "";
327 }
328
Hung-Te Lin262668f2010-05-28 10:32:02 -0700329 string::const_iterator dest = file_content_.begin() +
330 header_offset_ + prop_offset;
331 return string(dest, dest + prop_size);
332}
333
Hung-Te Lin21ef1a32010-06-02 18:13:47 -0700334string GoogleBinaryBlockUtil::get_property_name(PROPINDEX i) const {
335 uint32_t unused_off, unused_size;
336 const char *prop_name;
337
338 if (!find_property(i, &unused_off, &unused_size, &prop_name)) {
Hung-Te Lin21ef1a32010-06-02 18:13:47 -0700339 assert(!"invalid property index.");
340 return "";
341 }
342
343 return prop_name;
344}
345
Hung-Te Lin262668f2010-05-28 10:32:02 -0700346bool GoogleBinaryBlockUtil::set_hwid(const char *hwid) {
347 return set_property(PROP_HWID, hwid);
348}
349
350bool GoogleBinaryBlockUtil::set_rootkey(const std::string &value) {
351 return set_property(PROP_ROOTKEY, value);
352}
353
354bool GoogleBinaryBlockUtil::set_bmpfv(const string &value) {
355 return set_property(PROP_BMPFV, value);
356}
357
Hung-Te Lin08dc5f32010-06-03 14:35:47 -0700358bool GoogleBinaryBlockUtil::set_recovery_key(const string &value) {
359 return set_property(PROP_RCVKEY, value);
360}
361
Hung-Te Lin21ef1a32010-06-02 18:13:47 -0700362} // namespace vboot_reference
Hung-Te Lin262668f2010-05-28 10:32:02 -0700363
364#ifdef WITH_UTIL_MAIN
365
366///////////////////////////////////////////////////////////////////////
367// command line utilities
368
Hung-Te Lin21ef1a32010-06-02 18:13:47 -0700369#include <map>
370
371using vboot_reference::GoogleBinaryBlockUtil;
372
Hung-Te Lin262668f2010-05-28 10:32:02 -0700373// utility function: provide usage of this utility and exit.
374static void usagehelp_exit(const char *prog_name) {
375 printf(
376 "Utility to manage Google Binary Block (GBB)\n"
Hung-Te Lin21ef1a32010-06-02 18:13:47 -0700377 "Usage: %s [-g|-s] [OPTIONS] bios_file [output_file]\n"
378 "\n"
379 "GET MODE:\n"
380 "-g, --get (default)\tGet (read) from bios_file, "
Hung-Te Lin262668f2010-05-28 10:32:02 -0700381 "with following options:\n"
382 " --hwid \tReport hardware id (default).\n"
383 " -k, --rootkey=FILE \tFile name to export Root Key.\n"
384 " -b, --bmpfv=FILE \tFile name to export Bitmap FV.\n"
Hung-Te Lin08dc5f32010-06-03 14:35:47 -0700385 " --recoverykey=FILE\tFile name to export Recovery Key.\n"
Hung-Te Lin262668f2010-05-28 10:32:02 -0700386 "\n"
Hung-Te Lin21ef1a32010-06-02 18:13:47 -0700387 "SET MODE:\n"
Hung-Te Lin262668f2010-05-28 10:32:02 -0700388 "-s, --set \tSet (write) to bios_file, "
389 "with following options:\n"
Hung-Te Lin21ef1a32010-06-02 18:13:47 -0700390 " -o, --output=FILE \tNew file name for ouptput.\n"
Hung-Te Lin262668f2010-05-28 10:32:02 -0700391 " -i, --hwid=HWID \tThe new hardware id to be changed.\n"
392 " -k, --rootkey=FILE \tFile name of new Root Key.\n"
Hung-Te Lin21ef1a32010-06-02 18:13:47 -0700393 " -b, --bmpfv=FILE \tFile name of new Bitmap FV.\n"
Hung-Te Lin08dc5f32010-06-03 14:35:47 -0700394 " --recoverykey=FILE\tFile name of new Recovery Key.\n"
Hung-Te Lin262668f2010-05-28 10:32:02 -0700395 "\n"
Hung-Te Lin21ef1a32010-06-02 18:13:47 -0700396 "SAMPLE:\n"
Hung-Te Lin262668f2010-05-28 10:32:02 -0700397 " %s -g bios.bin\n"
398 " %s --set --hwid='New Model' -k key.bin bios.bin newbios.bin\n"
399 , prog_name, prog_name, prog_name);
400 exit(1);
401}
402
403// utility function: export a property from GBB to given file.
Hung-Te Lin21ef1a32010-06-02 18:13:47 -0700404// if filename was empty, export to console (screen).
Hung-Te Lin262668f2010-05-28 10:32:02 -0700405// return true on success, otherwise false.
Hung-Te Lin21ef1a32010-06-02 18:13:47 -0700406static bool export_property(GoogleBinaryBlockUtil::PROPINDEX idx,
407 const string &filename,
408 const GoogleBinaryBlockUtil &util) {
409 string prop_name = util.get_property_name(idx),
410 value = util.get_property(idx);
411 const char *name = prop_name.c_str();
Hung-Te Lin262668f2010-05-28 10:32:02 -0700412
Hung-Te Lin21ef1a32010-06-02 18:13:47 -0700413 if (filename.empty()) {
414 // write to console
415 printf("%s: %s\n", name, value.c_str());
416 } else {
417 const char *fn = filename.c_str();
418
419 if (!write_nonempty_file(fn, value)) {
420 fprintf(stderr, "error: failed to export %s to file: %s\n", name, fn);
421 return false;
422 }
423 printf(" - exported %s to file: %s\n", name, fn);
Hung-Te Lin262668f2010-05-28 10:32:02 -0700424 }
425
Hung-Te Lin262668f2010-05-28 10:32:02 -0700426 return true;
427}
428
Hung-Te Lin21ef1a32010-06-02 18:13:47 -0700429// utility function: import a property to GBB by given source (file or string).
Hung-Te Lin262668f2010-05-28 10:32:02 -0700430// return true on success, otherwise false.
431// is succesfully imported into GBB.
Hung-Te Lin21ef1a32010-06-02 18:13:47 -0700432static bool import_property(
433 GoogleBinaryBlockUtil::PROPINDEX idx, const string &source,
434 bool source_as_file, GoogleBinaryBlockUtil *putil) {
435 assert(!source.empty());
436 string prop_name = putil->get_property_name(idx);
Hung-Te Lin262668f2010-05-28 10:32:02 -0700437
Hung-Te Lin21ef1a32010-06-02 18:13:47 -0700438 if (source_as_file) {
439 printf(" - import %s from %s: ", prop_name.c_str(), source.c_str());
440 string v = read_nonempty_file(source.c_str());
441 if (v.empty()) {
442 printf("invalid file.\n");
443 return false;
444 }
445 if (!putil->set_property(idx, v)) {
446 printf("invalid content.\n");
447 return false;
448 }
449 printf("success.\n");
450 } else {
451 // source as string
452 string old_value = putil->get_property(idx);
453 bool result = putil->set_property(idx, source);
454 printf(" - %s changed from '%s' to '%s': %s\n",
455 prop_name.c_str(), old_value.c_str(), source.c_str(),
456 result ? "success" : "failed");
457 if (!result)
458 return false;
Hung-Te Lin262668f2010-05-28 10:32:02 -0700459 }
460
Hung-Te Lin262668f2010-05-28 10:32:02 -0700461 return true;
462}
463
464///////////////////////////////////////////////////////////////////////
465// main
466
467int main(int argc, char *argv[]) {
468 const char *myname = argv[0];
469 int err_stage = 0; // an indicator for error exits
470
Hung-Te Lin21ef1a32010-06-02 18:13:47 -0700471 // small parameter helper class
472 class OptPropertyMap: public
473 std::map<GoogleBinaryBlockUtil::PROPINDEX, string> {
474 public:
475 bool set_new_value(GoogleBinaryBlockUtil::PROPINDEX id, const string &v) {
476 if (find(id) != end())
477 return false;
Hung-Te Lin07c81172010-08-20 17:20:41 +0800478
Hung-Te Lin21ef1a32010-06-02 18:13:47 -0700479 (*this)[id] = v;
480 return true;
481 }
482 };
483 OptPropertyMap opt_props;
484
Hung-Te Lin262668f2010-05-28 10:32:02 -0700485 struct GBBUtilOptions {
486 bool get_mode, set_mode;
Hung-Te Lin21ef1a32010-06-02 18:13:47 -0700487 string input_fn, output_fn;
Hung-Te Lin262668f2010-05-28 10:32:02 -0700488 } myopts;
Hung-Te Lin262668f2010-05-28 10:32:02 -0700489 myopts.get_mode = myopts.set_mode = false;
Hung-Te Lin262668f2010-05-28 10:32:02 -0700490
491 // snippets for getopt_long
492 int option_index, opt;
493 static struct option long_options[] = {
Hung-Te Lin21ef1a32010-06-02 18:13:47 -0700494 {"get", 0, NULL, 'g' },
495 {"set", 0, NULL, 's' },
496 {"output", 1, NULL, 'o' },
497 {"hwid", 2, NULL, 'i' },
Hung-Te Lin262668f2010-05-28 10:32:02 -0700498 {"rootkey", 1, NULL, 'k' },
Hung-Te Lin21ef1a32010-06-02 18:13:47 -0700499 {"bmpfv", 1, NULL, 'b' },
Hung-Te Lin08dc5f32010-06-03 14:35:47 -0700500 {"recoverykey", 1, NULL, 'R' },
Hung-Te Lin21ef1a32010-06-02 18:13:47 -0700501 { NULL, 0, NULL, 0 },
Hung-Te Lin262668f2010-05-28 10:32:02 -0700502 };
Hung-Te Lin262668f2010-05-28 10:32:02 -0700503
504 // parse command line options
Hung-Te Lin21ef1a32010-06-02 18:13:47 -0700505 while ((opt = getopt_long(argc, argv, "gso:i:k:b:",
Hung-Te Lin262668f2010-05-28 10:32:02 -0700506 long_options, &option_index)) >= 0) {
507 switch (opt) {
508 case 'g':
509 myopts.get_mode = true;
510 break;
511
512 case 's':
513 myopts.set_mode = true;
514 break;
515
Hung-Te Lin21ef1a32010-06-02 18:13:47 -0700516 case 'o':
517 myopts.output_fn = optarg;
518 break;
519
Hung-Te Lin262668f2010-05-28 10:32:02 -0700520 case 'i':
Hung-Te Lin21ef1a32010-06-02 18:13:47 -0700521 if (!opt_props.set_new_value(
522 GoogleBinaryBlockUtil::PROP_HWID, optarg ? optarg : ""))
523 usagehelp_exit(myname);
Hung-Te Lin262668f2010-05-28 10:32:02 -0700524 break;
525
526 case 'k':
Hung-Te Lin21ef1a32010-06-02 18:13:47 -0700527 if (!opt_props.set_new_value(
528 GoogleBinaryBlockUtil::PROP_ROOTKEY, optarg))
529 usagehelp_exit(myname);
Hung-Te Lin262668f2010-05-28 10:32:02 -0700530 break;
531
532 case 'b':
Hung-Te Lin21ef1a32010-06-02 18:13:47 -0700533 if (!opt_props.set_new_value(
534 GoogleBinaryBlockUtil::PROP_BMPFV, optarg))
535 usagehelp_exit(myname);
Hung-Te Lin262668f2010-05-28 10:32:02 -0700536 break;
537
Hung-Te Lin08dc5f32010-06-03 14:35:47 -0700538 case 'R':
539 if (!opt_props.set_new_value(
540 GoogleBinaryBlockUtil::PROP_RCVKEY, optarg))
541 usagehelp_exit(myname);
542 break;
543
Hung-Te Lin262668f2010-05-28 10:32:02 -0700544 default:
545 case '?':
546 usagehelp_exit(myname);
547 break;
548 }
549 }
550 argc -= optind;
551 argv += optind;
552
Hung-Te Lin21ef1a32010-06-02 18:13:47 -0700553 // adjust non-dashed parameters
554 if (myopts.output_fn.empty() && argc == 2) {
555 myopts.output_fn = argv[1];
556 argc--;
557 }
Hung-Te Lin262668f2010-05-28 10:32:02 -0700558
Hung-Te Lin21ef1a32010-06-02 18:13:47 -0700559 // currently, the only parameter is 'input file'.
560 if (argc == 1) {
561 myopts.input_fn = argv[0];
562 } else {
563 usagehelp_exit(myname);
564 }
565
566 // stage: complete parameter parsing and checking
Hung-Te Lin262668f2010-05-28 10:32:02 -0700567 err_stage++;
568 if (myopts.get_mode == myopts.set_mode) {
Hung-Te Lin21ef1a32010-06-02 18:13:47 -0700569 if (myopts.get_mode) {
570 printf("error: please assign either get or set mode.\n");
571 return err_stage;
572 } else {
573 // enter 'get' mode by default, if not assigned.
574 myopts.get_mode = true;
575 }
576 }
577 if (myopts.get_mode && !myopts.output_fn.empty()) {
578 printf("error: get-mode does not create output files.\n");
Hung-Te Lin262668f2010-05-28 10:32:02 -0700579 return err_stage;
580 }
581
582 // stage: load image files
583 err_stage++;
Hung-Te Lin21ef1a32010-06-02 18:13:47 -0700584 GoogleBinaryBlockUtil util;
Hung-Te Lin262668f2010-05-28 10:32:02 -0700585
Hung-Te Lin21ef1a32010-06-02 18:13:47 -0700586 assert(!myopts.input_fn.empty());
587 if (!util.load_from_file(myopts.input_fn.c_str())) {
588 printf("error: cannot load valid BIOS file: %s\n", myopts.input_fn.c_str());
Hung-Te Lin262668f2010-05-28 10:32:02 -0700589 return err_stage;
590 }
591
592 // stage: processing by mode
593 err_stage++;
594 if (myopts.get_mode) {
595 // get mode
Hung-Te Lin21ef1a32010-06-02 18:13:47 -0700596 if (opt_props.empty()) // enable hwid by default
597 opt_props.set_new_value(GoogleBinaryBlockUtil::PROP_HWID, "");
Hung-Te Lin262668f2010-05-28 10:32:02 -0700598
Hung-Te Lin21ef1a32010-06-02 18:13:47 -0700599 for (OptPropertyMap::const_iterator i = opt_props.begin();
600 i != opt_props.end();
601 i++) {
602 export_property(i->first, i->second, util);
603 }
604
Hung-Te Lin262668f2010-05-28 10:32:02 -0700605 } else {
606 // set mode
607 assert(myopts.set_mode);
Hung-Te Lin21ef1a32010-06-02 18:13:47 -0700608
609 if (opt_props.empty()) {
Hung-Te Lin262668f2010-05-28 10:32:02 -0700610 printf("nothing to change. abort.\n");
611 return err_stage;
612 }
613
Hung-Te Lin21ef1a32010-06-02 18:13:47 -0700614 for (OptPropertyMap::const_iterator i = opt_props.begin();
615 i != opt_props.end();
616 i++) {
617 bool source_as_file = true;
618
619 // the hwid command line parameter was a simple string.
620 if (i->first == GoogleBinaryBlockUtil::PROP_HWID)
621 source_as_file = false;
622
623 if (!import_property(i->first, i->second, source_as_file, &util)) {
624 printf("error: cannot set properties. abort.\n");
Hung-Te Lin262668f2010-05-28 10:32:02 -0700625 return err_stage;
626 }
Hung-Te Lin262668f2010-05-28 10:32:02 -0700627 }
628
629 // stage: write output
630 err_stage++;
Hung-Te Lin21ef1a32010-06-02 18:13:47 -0700631
632 // use input filename (overwrite) by default
633 if (myopts.output_fn.empty())
634 myopts.output_fn = myopts.input_fn;
635
636 assert(!myopts.output_fn.empty());
637 if (!util.save_to_file(myopts.output_fn.c_str())) {
638 printf("error: cannot save to file: %s\n", myopts.output_fn.c_str());
Hung-Te Lin262668f2010-05-28 10:32:02 -0700639 return err_stage;
640 } else {
Hung-Te Lin21ef1a32010-06-02 18:13:47 -0700641 printf("successfully saved new image to: %s\n", myopts.output_fn.c_str());
Hung-Te Lin262668f2010-05-28 10:32:02 -0700642 }
643 }
644
645 return 0;
646}
647
648#endif // WITH_UTIL_MAIN