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