xref: /aosp_15_r20/external/vboot_reference/futility/cmd_gbb_utility.c (revision 8617a60d3594060b7ecbd21bc622a7c14f3cf2bc)
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