File: | 3rdparty/vboot/futility/cmd_gbb_utility.c |
Warning: | line 646, column 3 Value stored to 'gbb_base' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* Copyright 2014 The ChromiumOS Authors |
2 | * Use of this source code is governed by a BSD-style license that can be |
3 | * found in the LICENSE file. |
4 | */ |
5 | |
6 | #include <errno(*__errno_location ()).h> |
7 | #include <getopt.h> |
8 | #include <inttypes.h> |
9 | #include <stddef.h> |
10 | #include <stdint.h> |
11 | #include <stdio.h> |
12 | #include <stdlib.h> |
13 | #include <string.h> |
14 | #include <sys/stat.h> |
15 | #include <sys/types.h> |
16 | #include <unistd.h> |
17 | |
18 | #include "flash_helpers.h" |
19 | #include "futility.h" |
20 | #include "updater.h" |
21 | #include "updater_utils.h" |
22 | #include "2gbb_flags.h" |
23 | |
24 | #ifdef USE_FLASHROM |
25 | #define FLASH_ARG_HELP \ |
26 | " --flash \tRead from and write to flash" \ |
27 | ", ignore file arguments.\n" |
28 | #define FLASH_MORE_HELP \ |
29 | "In GET and SET mode, the following options modify the " \ |
30 | "behaviour of flashing. Presence of any of these implies " \ |
31 | "--flash.\n" \ |
32 | SHARED_FLASH_ARGS_HELP \ |
33 | "\n" |
34 | #else |
35 | #define FLASH_ARG_HELP |
36 | #define FLASH_MORE_HELP |
37 | #endif /* USE_FLASHROM */ |
38 | |
39 | static void print_help(int argc, char *argv[]) |
40 | { |
41 | printf("\n" |
42 | "Usage: " MYNAME"futility" " %s [-g|-s|-c] [OPTIONS] " |
43 | "[image_file] [output_file]\n" |
44 | "\n" |
45 | "GET MODE:\n" |
46 | "-g, --get (default)\tGet (read) from image_file or flash, " |
47 | "with following options:\n" |
48 | FLASH_ARG_HELP |
49 | " --hwid \tReport hardware id (default).\n" |
50 | " --flags \tReport header flags.\n" |
51 | " --digest \tReport digest of hwid (>= v1.2)\n" |
52 | " -k, --rootkey=FILE \tFile name to export Root Key.\n" |
53 | " -b, --bmpfv=FILE \tFile name to export Bitmap FV.\n" |
54 | " -r --recoverykey=FILE\tFile name to export Recovery Key.\n" |
55 | " -e --explicit \tReport header flags by name.\n" |
56 | "\n" |
57 | "SET MODE:\n" |
58 | "-s, --set \tSet (write) to flash or file, " |
59 | "with following options:\n" |
60 | FLASH_ARG_HELP |
61 | " -o, --output=FILE \tNew file name for ouptput.\n" |
62 | " --hwid=HWID \tThe new hardware id to be changed.\n" |
63 | " --flags=FLAGS \tThe new (numeric) flags value or +/- diff value.\n" |
64 | " -k, --rootkey=FILE \tFile name of new Root Key.\n" |
65 | " -b, --bmpfv=FILE \tFile name of new Bitmap FV.\n" |
66 | " -r --recoverykey=FILE\tFile name of new Recovery Key.\n" |
67 | "\n" |
68 | "CREATE MODE:\n" |
69 | "-c, --create=hwid_size,rootkey_size,bmpfv_size," |
70 | "recoverykey_size\n" |
71 | " \tCreate a GBB blob by given size list.\n\n" |
72 | FLASH_MORE_HELP |
73 | "SAMPLE:\n" |
74 | " %s -g image.bin\n" |
75 | " %s --set --hwid='New Model' -k key.bin" |
76 | " image.bin newimage.bin\n" |
77 | " %s -c 0x100,0x1000,0x03DE80,0x1000 gbb.blob\n\n" |
78 | "GBB Flags:\n" |
79 | " To get a developer-friendly device, try 0x18 (dev_mode boot_usb).\n" |
80 | " For early bringup development, try 0x40b9.\n", |
81 | argv[0], argv[0], argv[0], argv[0]); |
82 | for (vb2_gbb_flags_t flag = 1; flag; flag <<= 1) { |
83 | const char *name; |
84 | const char *description; |
85 | if (vb2_get_gbb_flag_description(flag, &name, &description) != |
86 | VB2_SUCCESS) |
87 | break; |
88 | printf(" 0x%08x\t%s\n" |
89 | " \t%s\n", |
90 | flag, name, description); |
91 | } |
92 | } |
93 | |
94 | enum { |
95 | OPT_HWID = 0x1000, |
96 | OPT_FLAGS, |
97 | OPT_DIGEST, |
98 | OPT_FLASH, |
99 | OPT_HELP, |
100 | }; |
101 | |
102 | /* Command line options */ |
103 | static struct option long_opts[] = { |
104 | SHARED_FLASH_ARGS_LONGOPTS |
105 | /* name has_arg *flag val */ |
106 | {"get", 0, NULL((void*)0), 'g'}, |
107 | {"set", 0, NULL((void*)0), 's'}, |
108 | {"create", 1, NULL((void*)0), 'c'}, |
109 | {"output", 1, NULL((void*)0), 'o'}, |
110 | {"rootkey", 1, NULL((void*)0), 'k'}, |
111 | {"bmpfv", 1, NULL((void*)0), 'b'}, |
112 | {"recoverykey", 1, NULL((void*)0), 'r'}, |
113 | {"hwid", 0, NULL((void*)0), OPT_HWID}, |
114 | {"flags", 0, NULL((void*)0), OPT_FLAGS}, |
115 | {"explicit", 0, NULL((void*)0), 'e'}, |
116 | {"digest", 0, NULL((void*)0), OPT_DIGEST}, |
117 | {"flash", 0, NULL((void*)0), OPT_FLASH}, |
118 | {"help", 0, NULL((void*)0), OPT_HELP}, |
119 | {NULL((void*)0), 0, NULL((void*)0), 0}, |
120 | }; |
121 | |
122 | static const char *short_opts = ":gsc:o:k:b:r:e" SHARED_FLASH_ARGS_SHORTOPTS; |
123 | |
124 | /* Change the has_arg field of a long_opts entry */ |
125 | static void opt_has_arg(const char *name, int val) |
126 | { |
127 | for (struct option *p = long_opts; p->name; p++) { |
128 | if (!strcmp(name, p->name)) { |
129 | p->has_arg = val; |
130 | break; |
131 | } |
132 | } |
133 | } |
134 | |
135 | #define GBB_SEARCH_STRIDE4 4 |
136 | static struct vb2_gbb_header *FindGbbHeader(uint8_t *ptr, size_t size) |
137 | { |
138 | size_t i; |
139 | struct vb2_gbb_header *tmp, *gbb_header = NULL((void*)0); |
140 | int count = 0; |
141 | |
142 | for (i = 0; i <= size - GBB_SEARCH_STRIDE4; i += GBB_SEARCH_STRIDE4) { |
143 | if (memcmp(ptr + i, VB2_GBB_SIGNATURE"$GBB", VB2_GBB_SIGNATURE_SIZE4)) |
144 | continue; |
145 | |
146 | /* Found something. See if it's any good. */ |
147 | tmp = (struct vb2_gbb_header *) (ptr + i); |
148 | if (futil_valid_gbb_header(tmp, size - i, NULL((void*)0))) |
149 | if (!count++) |
150 | gbb_header = tmp; |
151 | } |
152 | |
153 | switch (count) { |
154 | case 0: |
155 | return NULL((void*)0); |
156 | case 1: |
157 | return gbb_header; |
158 | default: |
159 | ERROR("Multiple GBB headers found\n")fprintf(stderr, "ERROR: %s: " "Multiple GBB headers found\n", __func__ ); |
160 | return NULL((void*)0); |
161 | } |
162 | } |
163 | |
164 | static uint8_t *create_gbb(const char *desc, off_t *sizeptr) |
165 | { |
166 | char *param, *e = NULL((void*)0); |
167 | size_t size = EXPECTED_VB2_GBB_HEADER_SIZE128; |
168 | int i = 0; |
169 | /* Danger Will Robinson! four entries ==> four paramater blocks */ |
170 | uint32_t val[] = { 0, 0, 0, 0 }; |
171 | |
172 | char *sizes = strdup(desc); |
173 | if (!sizes) { |
174 | ERROR("strdup() failed: %s\n", strerror(errno))fprintf(stderr, "ERROR: %s: " "strdup() failed: %s\n", __func__ , strerror((*__errno_location ())) ); |
175 | return NULL((void*)0); |
176 | } |
177 | |
178 | for (char *str = sizes; (param = strtok(str, ", ")) != NULL((void*)0); str = NULL((void*)0)) { |
179 | val[i] = (uint32_t) strtoul(param, &e, 0); |
180 | if (e && *e) { |
181 | ERROR("Invalid creation parameter: \"%s\"\n", param)fprintf(stderr, "ERROR: %s: " "Invalid creation parameter: \"%s\"\n" , __func__, param ); |
182 | free(sizes); |
183 | return NULL((void*)0); |
184 | } |
185 | size += val[i++]; |
186 | if (i > ARRAY_SIZE(val)(sizeof(val) / sizeof((val)[0]))) |
187 | break; |
188 | } |
189 | |
190 | uint8_t *buf = (uint8_t *) calloc(1, size); |
191 | if (!buf) { |
192 | ERROR("Can't malloc %zu bytes: %s\n", size, strerror(errno))fprintf(stderr, "ERROR: %s: " "Can't malloc %zu bytes: %s\n", __func__, size, strerror((*__errno_location ())) ); |
193 | free(sizes); |
194 | return NULL((void*)0); |
195 | } |
196 | if (sizeptr) |
197 | *sizeptr = size; |
198 | |
199 | struct vb2_gbb_header *gbb = (struct vb2_gbb_header *) buf; |
200 | memcpy(gbb->signature, VB2_GBB_SIGNATURE"$GBB", VB2_GBB_SIGNATURE_SIZE4); |
201 | gbb->major_version = VB2_GBB_MAJOR_VER1; |
202 | gbb->minor_version = VB2_GBB_MINOR_VER2; |
203 | gbb->header_size = EXPECTED_VB2_GBB_HEADER_SIZE128; |
204 | gbb->flags = 0; |
205 | |
206 | i = EXPECTED_VB2_GBB_HEADER_SIZE128; |
207 | gbb->hwid_offset = i; |
208 | gbb->hwid_size = val[0]; |
209 | i += val[0]; |
210 | |
211 | gbb->rootkey_offset = i; |
212 | gbb->rootkey_size = val[1]; |
213 | i += val[1]; |
214 | |
215 | gbb->bmpfv_offset = i; |
216 | gbb->bmpfv_size = val[2]; |
217 | i += val[2]; |
218 | |
219 | gbb->recovery_key_offset = i; |
220 | gbb->recovery_key_size = val[3]; |
221 | i += val[1]; |
222 | |
223 | free(sizes); |
224 | return buf; |
225 | } |
226 | |
227 | static uint8_t *read_entire_file(const char *filename, off_t *sizeptr) |
228 | { |
229 | uint8_t *buf = NULL((void*)0); |
230 | struct stat sb; |
231 | |
232 | FILE *fp = fopen(filename, "rb"); |
233 | if (!fp) { |
234 | ERROR("Unable to open %s for reading: %s\n", filename,fprintf(stderr, "ERROR: %s: " "Unable to open %s for reading: %s\n" , __func__, filename, strerror((*__errno_location ())) ) |
235 | strerror(errno))fprintf(stderr, "ERROR: %s: " "Unable to open %s for reading: %s\n" , __func__, filename, strerror((*__errno_location ())) ); |
236 | goto fail; |
237 | } |
238 | |
239 | if (fstat(fileno(fp), &sb)) { |
240 | ERROR("Can't fstat %s: %s\n", filename, strerror(errno))fprintf(stderr, "ERROR: %s: " "Can't fstat %s: %s\n", __func__ , filename, strerror((*__errno_location ())) ); |
241 | goto fail; |
242 | } |
243 | if (sizeptr) |
244 | *sizeptr = sb.st_size; |
245 | |
246 | buf = (uint8_t *) malloc(sb.st_size); |
247 | if (!buf) { |
248 | ERROR("Can't malloc %" PRIi64 " bytes: %s\n", sb.st_size,fprintf(stderr, "ERROR: %s: " "Can't malloc %" "l" "i" " bytes: %s\n" , __func__, sb.st_size, strerror((*__errno_location ())) ) |
249 | strerror(errno))fprintf(stderr, "ERROR: %s: " "Can't malloc %" "l" "i" " bytes: %s\n" , __func__, sb.st_size, strerror((*__errno_location ())) ); |
250 | goto fail; |
251 | } |
252 | |
253 | if (1 != fread(buf, sb.st_size, 1, fp)) { |
254 | ERROR("Unable to read from %s: %s\n", filename,fprintf(stderr, "ERROR: %s: " "Unable to read from %s: %s\n", __func__, filename, strerror((*__errno_location ())) ) |
255 | strerror(errno))fprintf(stderr, "ERROR: %s: " "Unable to read from %s: %s\n", __func__, filename, strerror((*__errno_location ())) ); |
256 | goto fail; |
257 | } |
258 | |
259 | if (fclose(fp)) { |
260 | ERROR("Unable to close %s: %s\n", filename, strerror(errno))fprintf(stderr, "ERROR: %s: " "Unable to close %s: %s\n", __func__ , filename, strerror((*__errno_location ())) ); |
261 | fp = NULL((void*)0); /* Don't try to close it again */ |
262 | goto fail; |
263 | } |
264 | |
265 | return buf; |
266 | |
267 | fail: |
268 | if (buf) |
269 | free(buf); |
270 | |
271 | if (fp && fclose(fp)) |
272 | ERROR("Unable to close %s: %s\n", filename, strerror(errno))fprintf(stderr, "ERROR: %s: " "Unable to close %s: %s\n", __func__ , filename, strerror((*__errno_location ())) ); |
273 | return NULL((void*)0); |
274 | } |
275 | |
276 | static int read_from_file(const char *msg, const char *filename, |
277 | uint8_t *start, uint32_t size) |
278 | { |
279 | struct stat sb; |
280 | size_t count; |
281 | int r = 0; |
282 | |
283 | FILE *fp = fopen(filename, "rb"); |
284 | if (!fp) { |
285 | r = errno(*__errno_location ()); |
286 | ERROR("Unable to open %s for reading: %s\n", filename, strerror(r))fprintf(stderr, "ERROR: %s: " "Unable to open %s for reading: %s\n" , __func__, filename, strerror(r) ); |
287 | return r; |
288 | } |
289 | |
290 | if (fstat(fileno(fp), &sb)) { |
291 | r = errno(*__errno_location ()); |
292 | ERROR("Can't fstat %s: %s\n", filename, strerror(r))fprintf(stderr, "ERROR: %s: " "Can't fstat %s: %s\n", __func__ , filename, strerror(r) ); |
293 | goto done_close; |
294 | } |
295 | |
296 | if (sb.st_size > size) { |
297 | ERROR("File %s exceeds capacity (%" PRIu32 ")\n", filename, size)fprintf(stderr, "ERROR: %s: " "File %s exceeds capacity (%" "u" ")\n", __func__, filename, size ); |
298 | r = -1; |
299 | goto done_close; |
300 | } |
301 | |
302 | /* Wipe existing data. */ |
303 | memset(start, 0, size); |
304 | |
305 | /* It's okay if we read less than size. That's just the max. */ |
306 | count = fread(start, 1, size, fp); |
307 | if (ferror(fp)) { |
308 | r = errno(*__errno_location ()); |
309 | ERROR("Read %zu/%" PRIi64 " bytes from %s: %s\n", count,fprintf(stderr, "ERROR: %s: " "Read %zu/%" "l" "i" " bytes from %s: %s\n" , __func__, count, sb.st_size, filename, strerror(r) ) |
310 | sb.st_size, filename, strerror(r))fprintf(stderr, "ERROR: %s: " "Read %zu/%" "l" "i" " bytes from %s: %s\n" , __func__, count, sb.st_size, filename, strerror(r) ); |
311 | } |
312 | |
313 | done_close: |
314 | if (fclose(fp)) { |
315 | int e = errno(*__errno_location ()); |
316 | ERROR("Unable to close %s: %s\n", filename, strerror(e))fprintf(stderr, "ERROR: %s: " "Unable to close %s: %s\n", __func__ , filename, strerror(e) ); |
317 | if (!r) |
318 | r = e; |
319 | } |
320 | |
321 | if (!r && msg) |
322 | printf(" - import %s from %s: success\n", msg, filename); |
323 | |
324 | return r; |
325 | } |
326 | |
327 | /* Read firmware from flash. */ |
328 | static uint8_t *read_from_flash(struct updater_config *cfg, off_t *filesize) |
329 | { |
330 | #ifdef USE_FLASHROM |
331 | /* |
332 | * Read the FMAP region as well, so that a subsequet write won't |
333 | * require another read of FMAP. |
334 | */ |
335 | const char * const regions[] = {FMAP_RO_FMAP, FMAP_RO_GBB}; |
336 | if (flashrom_read_image(&cfg->image_current, regions, |
337 | ARRAY_SIZE(regions)(sizeof(regions) / sizeof((regions)[0])), cfg->verbosity + 1)) |
338 | return NULL((void*)0); |
339 | uint8_t *ret = cfg->image_current.data; |
340 | cfg->image_current.data = NULL((void*)0); |
341 | *filesize = cfg->image_current.size; |
342 | cfg->image_current.size = 0; |
343 | return ret; |
344 | #else |
345 | return NULL((void*)0); |
346 | #endif /* USE_FLASHROM */ |
347 | } |
348 | |
349 | /* Write firmware to flash. Takes ownership of inbuf and outbuf data. */ |
350 | static int write_to_flash(struct updater_config *cfg, uint8_t *outbuf, |
351 | off_t filesize) |
352 | { |
353 | #ifdef USE_FLASHROM |
354 | if (is_ap_write_protection_enabled(cfg)) { |
355 | ERROR("You must disable write protection before setting flags.\n")fprintf(stderr, "ERROR: %s: " "You must disable write protection before setting flags.\n" , __func__ ); |
356 | return -1; |
357 | } |
358 | cfg->image.data = outbuf; |
359 | cfg->image.size = filesize; |
360 | |
361 | const char *sections[] = {FMAP_RO_GBB}; |
362 | int ret = write_system_firmware(cfg, &cfg->image, sections, |
363 | ARRAY_SIZE(sections)(sizeof(sections) / sizeof((sections)[0]))); |
364 | |
365 | cfg->image.data = NULL((void*)0); |
366 | cfg->image.size = 0; |
367 | return ret; |
368 | #else |
369 | return 1; |
370 | #endif /* USE_FLASHROM */ |
371 | } |
372 | |
373 | static int parse_flag_value(const char *s, vb2_gbb_flags_t *val) |
374 | { |
375 | int sign = 0; |
376 | |
377 | if (!strlen(s)) |
378 | return -1; |
379 | |
380 | if (s[0] == '+') |
381 | sign = 1; |
382 | else if (s[0] == '-') |
383 | sign = 2; |
384 | |
385 | const char *ss = !sign ? s : &s[1]; |
386 | char *e = NULL((void*)0); |
387 | *val = strtoul(ss, &e, 0); |
388 | if (e && *e) { |
389 | ERROR("Invalid flags value: %s\n", ss)fprintf(stderr, "ERROR: %s: " "Invalid flags value: %s\n", __func__ , ss ); |
390 | return -1; |
391 | } |
392 | |
393 | return sign; |
394 | } |
395 | |
396 | static int do_gbb(int argc, char *argv[]) |
397 | { |
398 | enum do_what_now { DO_GET, DO_SET, DO_CREATE } mode = DO_GET; |
399 | char *infile = NULL((void*)0); |
400 | char *outfile = NULL((void*)0); |
401 | char *opt_create = NULL((void*)0); |
402 | char *opt_rootkey = NULL((void*)0); |
403 | char *opt_bmpfv = NULL((void*)0); |
404 | char *opt_recoverykey = NULL((void*)0); |
405 | char *opt_hwid = NULL((void*)0); |
406 | char *opt_flags = NULL((void*)0); |
407 | bool_Bool sel_hwid = false0; |
408 | bool_Bool sel_digest = false0; |
409 | bool_Bool sel_flags = false0; |
410 | int explicit_flags = 0; |
411 | uint8_t *inbuf = NULL((void*)0); |
412 | off_t filesize; |
413 | uint8_t *outbuf = NULL((void*)0); |
414 | int i; |
415 | struct updater_config *cfg = NULL((void*)0); |
416 | struct updater_config_arguments args = {0}; |
417 | int errorcnt = 0; |
418 | |
419 | |
420 | opterr = 0; /* quiet, you */ |
421 | while ((i = getopt_long(argc, argv, short_opts, long_opts, 0)) != -1) { |
422 | #ifdef USE_FLASHROM |
423 | if (handle_flash_argument(&args, i, optarg)) |
424 | continue; |
425 | #endif |
426 | switch (i) { |
427 | case 'g': |
428 | mode = DO_GET; |
429 | opt_has_arg("flags", 0); |
430 | opt_has_arg("hwid", 0); |
431 | break; |
432 | case 's': |
433 | mode = DO_SET; |
434 | opt_has_arg("flags", 1); |
435 | opt_has_arg("hwid", 1); |
436 | break; |
437 | case 'c': |
438 | mode = DO_CREATE; |
439 | opt_create = optarg; |
440 | break; |
441 | case 'o': |
442 | outfile = optarg; |
443 | break; |
444 | case 'k': |
445 | opt_rootkey = optarg; |
446 | break; |
447 | case 'b': |
448 | opt_bmpfv = optarg; |
449 | break; |
450 | case 'r': |
451 | opt_recoverykey = optarg; |
452 | break; |
453 | case OPT_HWID: |
454 | /* --hwid is optional: null might be okay */ |
455 | opt_hwid = optarg; |
456 | sel_hwid = true1; |
457 | break; |
458 | case OPT_FLAGS: |
459 | /* --flags is optional: null might be okay */ |
460 | opt_flags = optarg; |
461 | sel_flags = true1; |
462 | break; |
463 | case 'e': |
464 | sel_flags = true1; |
465 | explicit_flags = 1; |
466 | break; |
467 | case OPT_DIGEST: |
468 | sel_digest = true1; |
469 | break; |
470 | case OPT_FLASH: |
471 | #ifndef USE_FLASHROM |
472 | ERROR("futility was built without flashrom support\n")fprintf(stderr, "ERROR: %s: " "futility was built without flashrom support\n" , __func__ ); |
473 | return 1; |
474 | #endif |
475 | args.use_flash = 1; |
476 | break; |
477 | case OPT_HELP: |
478 | print_help(argc, argv); |
479 | return !!errorcnt; |
480 | |
481 | case '?': |
482 | errorcnt++; |
483 | if (optopt) |
484 | ERROR("Unrecognized option: -%c\n", optopt)fprintf(stderr, "ERROR: %s: " "Unrecognized option: -%c\n", __func__ , optopt ); |
485 | else if (argv[optind - 1]) |
486 | ERROR("Unrecognized option (possibly \"%s\")\n",fprintf(stderr, "ERROR: %s: " "Unrecognized option (possibly \"%s\")\n" , __func__, argv[optind - 1] ) |
487 | argv[optind - 1])fprintf(stderr, "ERROR: %s: " "Unrecognized option (possibly \"%s\")\n" , __func__, argv[optind - 1] ); |
488 | else |
489 | ERROR("Unrecognized option\n")fprintf(stderr, "ERROR: %s: " "Unrecognized option\n", __func__ ); |
490 | break; |
491 | case ':': |
492 | errorcnt++; |
493 | if (argv[optind - 1]) |
494 | ERROR("Missing argument to -%c (%s)\n", optopt,fprintf(stderr, "ERROR: %s: " "Missing argument to -%c (%s)\n" , __func__, optopt, argv[optind - 1] ) |
495 | argv[optind - 1])fprintf(stderr, "ERROR: %s: " "Missing argument to -%c (%s)\n" , __func__, optopt, argv[optind - 1] ); |
496 | else |
497 | ERROR("Missing argument to -%c\n", optopt)fprintf(stderr, "ERROR: %s: " "Missing argument to -%c\n", __func__ , optopt ); |
498 | break; |
499 | default: |
500 | errorcnt++; |
501 | ERROR("While parsing options\n")fprintf(stderr, "ERROR: %s: " "While parsing options\n", __func__ ); |
502 | } |
503 | } |
504 | |
505 | /* Problems? */ |
506 | if (errorcnt) { |
507 | print_help(argc, argv); |
508 | return 1; |
509 | } |
510 | |
511 | if (args.use_flash) { |
512 | if (setup_flash(&cfg, &args)) { |
513 | ERROR("While preparing flash\n")fprintf(stderr, "ERROR: %s: " "While preparing flash\n", __func__ ); |
514 | return 1; |
515 | } |
516 | } |
517 | |
518 | /* Now try to do something */ |
519 | switch (mode) { |
520 | case DO_GET: |
521 | if (args.use_flash) { |
522 | inbuf = read_from_flash(cfg, &filesize); |
523 | } else { |
524 | if (argc - optind < 1) { |
525 | ERROR("Missing input filename\n")fprintf(stderr, "ERROR: %s: " "Missing input filename\n", __func__ ); |
526 | print_help(argc, argv); |
527 | errorcnt++; |
528 | break; |
529 | } |
530 | infile = argv[optind++]; |
531 | inbuf = read_entire_file(infile, &filesize); |
532 | } |
533 | if (!inbuf) { |
534 | errorcnt++; |
535 | break; |
536 | } |
537 | |
538 | /* With no args, show the HWID */ |
539 | if (!opt_rootkey && !opt_bmpfv && !opt_recoverykey |
540 | && !sel_flags && !sel_digest) |
541 | sel_hwid = true1; |
542 | |
543 | struct vb2_gbb_header *gbb = FindGbbHeader(inbuf, filesize); |
544 | if (!gbb) { |
545 | ERROR("No GBB found in %s\n", infile)fprintf(stderr, "ERROR: %s: " "No GBB found in %s\n", __func__ , infile ); |
546 | errorcnt++; |
547 | break; |
548 | } |
549 | uint8_t *gbb_base = (uint8_t *) gbb; |
550 | |
551 | /* Get the stuff */ |
552 | if (sel_hwid) |
553 | printf("hardware_id: %s\n", |
554 | gbb->hwid_size ? (char *)(gbb_base + |
555 | gbb-> |
556 | hwid_offset) : ""); |
557 | if (sel_digest) |
558 | print_hwid_digest(gbb, "digest: "); |
559 | |
560 | if (sel_flags) |
561 | printf("flags: 0x%08x\n", gbb->flags); |
562 | if (opt_rootkey) |
563 | if (write_to_file(" - exported root_key to file:", |
564 | opt_rootkey, |
565 | gbb_base + gbb->rootkey_offset, |
566 | gbb->rootkey_size)) { |
567 | errorcnt++; |
568 | break; |
569 | } |
570 | if (opt_bmpfv) |
571 | if (write_to_file( |
572 | " - exported bmp_fv to file:", opt_bmpfv, |
573 | gbb_base + gbb->bmpfv_offset, |
574 | gbb->bmpfv_size)) { |
575 | errorcnt++; |
576 | break; |
577 | } |
578 | if (opt_recoverykey) |
579 | if (write_to_file(" - exported recovery_key to file:", |
580 | opt_recoverykey, |
581 | gbb_base + gbb->recovery_key_offset, |
582 | gbb->recovery_key_size)) { |
583 | errorcnt++; |
584 | break; |
585 | } |
586 | if (explicit_flags) { |
587 | vb2_gbb_flags_t remaining_flags = gbb->flags; |
588 | while (remaining_flags) { |
589 | vb2_gbb_flags_t lsb_flag = |
590 | remaining_flags & -remaining_flags; |
591 | remaining_flags &= ~lsb_flag; |
592 | const char *name; |
593 | const char *description; |
594 | if (vb2_get_gbb_flag_description( |
595 | lsb_flag, &name, &description) == |
596 | VB2_SUCCESS) { |
597 | printf("%s\n", name); |
598 | } else { |
599 | printf("unknown set flag: 0x%08x\n", |
600 | lsb_flag); |
601 | } |
602 | } |
603 | } |
604 | break; |
605 | |
606 | case DO_SET: |
607 | if (args.use_flash) { |
608 | inbuf = read_from_flash(cfg, &filesize); |
609 | } else { |
610 | if (argc - optind < 1) { |
611 | ERROR("Missing input filename\n")fprintf(stderr, "ERROR: %s: " "Missing input filename\n", __func__ ); |
612 | print_help(argc, argv); |
613 | errorcnt++; |
614 | break; |
615 | } |
616 | infile = argv[optind++]; |
617 | inbuf = read_entire_file(infile, &filesize); |
618 | if (!outfile) |
619 | outfile = (argc - optind < 1) ? infile |
620 | : argv[optind++]; |
621 | } |
622 | if (!inbuf) { |
623 | errorcnt++; |
624 | break; |
625 | } |
626 | |
627 | if (sel_hwid && !opt_hwid) { |
628 | ERROR("Missing new HWID value\n")fprintf(stderr, "ERROR: %s: " "Missing new HWID value\n", __func__ ); |
629 | print_help(argc, argv); |
630 | errorcnt++; |
631 | break; |
632 | } |
633 | if (sel_flags && (!opt_flags || !*opt_flags)) { |
634 | ERROR("Missing new flags value\n")fprintf(stderr, "ERROR: %s: " "Missing new flags value\n", __func__ ); |
635 | print_help(argc, argv); |
636 | errorcnt++; |
637 | break; |
638 | } |
639 | |
640 | gbb = FindGbbHeader(inbuf, filesize); |
641 | if (!gbb) { |
642 | ERROR("No GBB found in %s\n", infile)fprintf(stderr, "ERROR: %s: " "No GBB found in %s\n", __func__ , infile ); |
643 | errorcnt++; |
644 | break; |
645 | } |
646 | gbb_base = (uint8_t *) gbb; |
Value stored to 'gbb_base' is never read | |
647 | |
648 | outbuf = (uint8_t *) malloc(filesize); |
649 | if (!outbuf) { |
650 | ERROR("Can't malloc %" PRIi64 " bytes: %s\n", filesize,fprintf(stderr, "ERROR: %s: " "Can't malloc %" "l" "i" " bytes: %s\n" , __func__, filesize, strerror((*__errno_location ())) ) |
651 | strerror(errno))fprintf(stderr, "ERROR: %s: " "Can't malloc %" "l" "i" " bytes: %s\n" , __func__, filesize, strerror((*__errno_location ())) ); |
652 | errorcnt++; |
653 | break; |
654 | } |
655 | |
656 | /* Switch pointers to outbuf */ |
657 | memcpy(outbuf, inbuf, filesize); |
658 | gbb = FindGbbHeader(outbuf, filesize); |
659 | if (!gbb) { |
660 | ERROR("INTERNAL ERROR: No GBB found in outbuf\n")fprintf(stderr, "ERROR: %s: " "INTERNAL ERROR: No GBB found in outbuf\n" , __func__ ); |
661 | errorcnt++; |
662 | break; |
663 | } |
664 | gbb_base = (uint8_t *) gbb; |
665 | |
666 | if (opt_hwid) { |
667 | if (strlen(opt_hwid) + 1 > gbb->hwid_size) { |
668 | ERROR("null-terminated HWID exceeds capacity (%d)\n",fprintf(stderr, "ERROR: %s: " "null-terminated HWID exceeds capacity (%d)\n" , __func__, gbb->hwid_size ) |
669 | gbb->hwid_size)fprintf(stderr, "ERROR: %s: " "null-terminated HWID exceeds capacity (%d)\n" , __func__, gbb->hwid_size ); |
670 | errorcnt++; |
671 | break; |
672 | } |
673 | /* Wipe data before writing new value. */ |
674 | memset(gbb_base + gbb->hwid_offset, 0, |
675 | gbb->hwid_size); |
676 | strcpy((char *)(gbb_base + gbb->hwid_offset), |
677 | opt_hwid); |
678 | update_hwid_digest(gbb); |
679 | } |
680 | |
681 | if (opt_flags) { |
682 | vb2_gbb_flags_t val; |
683 | const int flag_sign = parse_flag_value(opt_flags, &val); |
684 | if (flag_sign < 0) { |
685 | errorcnt++; |
686 | break; |
687 | } |
688 | if (flag_sign > 0) |
689 | /* flag_sign := 1 => +ve and flag_sign := 2 => -ve. */ |
690 | gbb->flags = flag_sign == 1 ? (gbb->flags | val) : (gbb->flags & ~val); |
691 | else |
692 | gbb->flags = val; |
693 | } |
694 | |
695 | if (opt_rootkey) { |
696 | if (read_from_file("root_key", opt_rootkey, |
697 | gbb_base + gbb->rootkey_offset, |
698 | gbb->rootkey_size)) { |
699 | errorcnt++; |
700 | break; |
701 | } |
702 | } |
703 | if (opt_bmpfv) |
704 | if (read_from_file("bmp_fv", opt_bmpfv, |
705 | gbb_base + gbb->bmpfv_offset, |
706 | gbb->bmpfv_size)) { |
707 | errorcnt++; |
708 | break; |
709 | } |
710 | if (opt_recoverykey) |
711 | if (read_from_file("recovery_key", opt_recoverykey, |
712 | gbb_base + gbb->recovery_key_offset, |
713 | gbb->recovery_key_size)) { |
714 | errorcnt++; |
715 | break; |
716 | } |
717 | |
718 | /* Write it out if there are no problems. */ |
719 | if (!errorcnt) { |
720 | if (args.use_flash) { |
721 | if (write_to_flash(cfg, outbuf, filesize)) { |
722 | errorcnt++; |
723 | break; |
724 | } |
725 | } else if (write_to_file( |
726 | "successfully saved new image to:", |
727 | outfile, outbuf, filesize)) { |
728 | errorcnt++; |
729 | break; |
730 | } |
731 | } |
732 | break; |
733 | |
734 | case DO_CREATE: |
735 | if (!outfile) { |
736 | if (argc - optind < 1) { |
737 | ERROR("Missing output filename\n")fprintf(stderr, "ERROR: %s: " "Missing output filename\n", __func__ ); |
738 | print_help(argc, argv); |
739 | errorcnt++; |
740 | break; |
741 | } |
742 | outfile = argv[optind++]; |
743 | } |
744 | /* Parse the creation args */ |
745 | outbuf = create_gbb(opt_create, &filesize); |
746 | if (!outbuf) { |
747 | ERROR("Unable to parse creation spec (%s)\n", opt_create)fprintf(stderr, "ERROR: %s: " "Unable to parse creation spec (%s)\n" , __func__, opt_create ); |
748 | print_help(argc, argv); |
749 | errorcnt++; |
750 | break; |
751 | } |
752 | if (!errorcnt) |
753 | if (write_to_file("successfully created new GBB to:", |
754 | outfile, outbuf, filesize)) { |
755 | errorcnt++; |
756 | break; |
757 | } |
758 | break; |
759 | } |
760 | |
761 | if (args.use_flash) |
762 | teardown_flash(cfg); |
763 | if (inbuf) |
764 | free(inbuf); |
765 | if (outbuf) |
766 | free(outbuf); |
767 | return !!errorcnt; |
768 | } |
769 | |
770 | DECLARE_FUTIL_COMMAND(gbb, do_gbb, VBOOT_VERSION_ALL,const struct futil_cmd_t __cmd_gbb = { .name = "gbb", .handler = do_gbb, .version = VBOOT_VERSION_ALL, .shorthelp = "Manipulate the Google Binary Block (GBB)" , } |
771 | "Manipulate the Google Binary Block (GBB)")const struct futil_cmd_t __cmd_gbb = { .name = "gbb", .handler = do_gbb, .version = VBOOT_VERSION_ALL, .shorthelp = "Manipulate the Google Binary Block (GBB)" , }; |
772 | DECLARE_FUTIL_COMMAND(gbb_utility, do_gbb, VBOOT_VERSION_ALL,const struct futil_cmd_t __cmd_gbb_utility = { .name = "gbb_utility" , .handler = do_gbb, .version = VBOOT_VERSION_ALL, .shorthelp = "Legacy name for `gbb` command", } |
773 | "Legacy name for `gbb` command")const struct futil_cmd_t __cmd_gbb_utility = { .name = "gbb_utility" , .handler = do_gbb, .version = VBOOT_VERSION_ALL, .shorthelp = "Legacy name for `gbb` command", }; |