• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright 2018 The ChromiumOS Authors
2  * Use of this source code is governed by a BSD-style license that can be
3  * found in the LICENSE file.
4  *
5  * The command line tool to invoke firmware updater.
6  */
7 
8 #include <assert.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <getopt.h>
12 
13 #include "futility.h"
14 #include "updater.h"
15 
16 #ifdef USE_FLASHROM
17 
18 enum {
19 	OPT_DUMMY = 0x1000,
20 	OPT_DETECT_MODEL_ONLY,
21 	OPT_FACTORY,
22 	OPT_FAST,
23 	OPT_FORCE,
24 	OPT_GBB_FLAGS,
25 	OPT_HOST_ONLY,
26 	OPT_MANIFEST,
27 	OPT_PARSEABLE_MANIFEST,
28 	OPT_MODEL,
29 	OPT_OUTPUT_DIR,
30 	OPT_QUIRKS,
31 	OPT_QUIRKS_LIST,
32 	OPT_REPACK,
33 	OPT_SERVO_NORESET,
34 	OPT_SIGNATURE,
35 	OPT_SYS_PROPS,
36 	OPT_UNLOCK_ME,
37 	OPT_UNPACK,
38 	OPT_WRITE_PROTECTION,
39 };
40 
41 /* Command line options */
42 static struct option const long_opts[] = {
43 	SHARED_FLASH_ARGS_LONGOPTS
44 	/* name  has_arg *flag val */
45 	{"help", 0, NULL, 'h'},
46 	{"debug", 0, NULL, 'd'},
47 	{"verbose", 0, NULL, 'v'},
48 
49 	{"image", 1, NULL, 'i'},
50 	{"ec_image", 1, NULL, 'e'},
51 	{"try", 0, NULL, 't'},
52 	{"archive", 1, NULL, 'a'},
53 	{"mode", 1, NULL, 'm'},
54 
55 	{"detect-model-only", 0, NULL, OPT_DETECT_MODEL_ONLY},
56 	{"factory", 0, NULL, OPT_FACTORY},
57 	{"fast", 0, NULL, OPT_FAST},
58 	{"force", 0, NULL, OPT_FORCE},
59 	{"gbb_flags", 1, NULL, OPT_GBB_FLAGS},
60 	{"host_only", 0, NULL, OPT_HOST_ONLY},
61 	{"quirks", 1, NULL, OPT_QUIRKS},
62 	{"list-quirks", 0, NULL, OPT_QUIRKS_LIST},
63 	{"manifest", 0, NULL, OPT_MANIFEST},
64 	{"parseable-manifest", 0, NULL, OPT_PARSEABLE_MANIFEST},
65 	{"model", 1, NULL, OPT_MODEL},
66 	{"output_dir", 1, NULL, OPT_OUTPUT_DIR},
67 	{"repack", 1, NULL, OPT_REPACK},
68 	{"signature_id", 1, NULL, OPT_SIGNATURE},
69 	{"sys_props", 1, NULL, OPT_SYS_PROPS},
70 	{"unlock_me", 0, NULL, OPT_UNLOCK_ME},
71 	{"unpack", 1, NULL, OPT_UNPACK},
72 	{"wp", 1, NULL, OPT_WRITE_PROTECTION},
73 
74 	/* TODO(hungte) Remove following deprecated options. */
75 	{"noupdate_ec", 0, NULL, OPT_HOST_ONLY},
76 	{"nocheck_keys", 0, NULL, OPT_FORCE},
77 	{"update_main", 0, NULL, OPT_DUMMY},
78 	{"update_ec", 0, NULL, OPT_DUMMY},
79 	{"check_keys", 0, NULL, OPT_DUMMY},
80 
81 	{NULL, 0, NULL, 0},
82 };
83 
84 static const char *const short_opts =
85 	"hdvi:e:ta:m:" SHARED_FLASH_ARGS_SHORTOPTS;
86 
print_help(int argc,char * argv[])87 static void print_help(int argc, char *argv[])
88 {
89 	printf("\n"
90 		"Usage:  " MYNAME " %s [OPTIONS]\n"
91 		"\n"
92 		"Updates firmware in one of the following modes (default to recovery):\n"
93 		"  autoupdate:\tUpdate RW[A|B], or recovery if RO changed.\n"
94 		"  recovery:  \tUpdate RW[A&B], (RO, RO:GBB[keys] - if RO changed)\n"
95 		"  factory:   \tUpdate RW[A&B],  RO, RO:GBB[keys,flags]\n"
96 		"\n"
97 		"Note: firmware sections with PRESERVE flags like VPD and\n"
98 		"      HWID in GBB are always preserved.\n"
99 		"      GBB flags are preserved in autoupdate and recovery modes.\n"
100 		"\n"
101 		"OPTIONS:\n"
102 		"\n"
103 		"-i, --image=FILE    \tAP (host) firmware image (image.bin)\n"
104 		"-e, --ec_image=FILE \tEC firmware image (i.e, ec.bin)\n"
105 		"-t, --try           \tTry A/B update on reboot if possible\n"
106 		"-a, --archive=PATH  \tRead resources from archive\n"
107 		"    --unpack=DIR    \tExtracts archive to DIR\n"
108 		"    --fast          \tReduce read cycles and do not verify\n"
109 		"    --quirks=LIST   \tSpecify the quirks to apply\n"
110 		"    --list-quirks   \tPrint all available quirks\n"
111 		"-m, --mode=MODE     \tRun updater in the specified mode\n"
112 		"    --manifest      \tScan the archive to print a manifest in JSON\n"
113 		"    --parseable-manifest\n"
114 		"                    \tScan the archive to print a manifest\n"
115 		"                    \tin shell-parseable format\n"
116 		SHARED_FLASH_ARGS_HELP
117 		"\n"
118 		" * Option --manifest requires either -a,--archive or -i,--image\n"
119 		"   With -i,--image additional images are accepted with options\n"
120 		"   -e,--ec_image.\n"
121 		" * If both --manifest and --fast are specified, the updater\n"
122 		"   will not scan the archive and simply dump the previously\n"
123 		"   cached manifest (may be out-dated) from the archive.\n"
124 		"   Works only with -a,--archive option.\n"
125 		" * Use of -p,--programmer with option other than '%s',\n"
126 		"   or with --ccd effectively disables ability to update EC\n"
127 		"   firmware images.\n"
128 		" * Emulation works only with the AP (host) firmware image, and\n"
129 		"   does not support the EC firmware image.\n"
130 		" * Model detection with option --detect-model-only requires\n"
131 		"   archive path -a,--archive\n"
132 		" * The --quirks provides a set of options to override the\n"
133 		"   default behavior. Run --list-quirks to get the options,\n"
134 		"   and --quirks OPTION to turn on. To disable a quirk that\n"
135 		"   was default turned on from the firmware image CBFS, do\n"
136 		"   --quirks OPTION=0 to turn off.\n"
137 		"\n"
138 		"Legacy and compatibility options:\n"
139 		"    --factory       \tAlias for --mode=factory\n"
140 		"    --force         \tForce update (skip checking contents)\n"
141 		"    --output_dir=DIR\tSpecify the target for --mode=output\n"
142 		"    --unlock_me     \t(deprecated) Unlock the Intel ME before flashing\n"
143 		"    --signature_id=S\t(deprecated) Same as --model\n"
144 		"\n"
145 		"Debugging and testing options:\n"
146 		"    --wp=1|0        \tSpecify write protection status\n"
147 		"    --host_only     \tUpdate only AP (host) firmware\n"
148 		"    --model=MODEL   \tOverride system model for images\n"
149 		"    --detect-model-only\tDetect model by reading the FRID and exit\n"
150 		"    --gbb_flags=FLAG\tOverride new GBB flags\n"
151 		"    --sys_props=LIST\tList of system properties to override\n"
152 		"-d, --debug         \tPrint debugging messages\n"
153 		"-v, --verbose       \tPrint verbose messages\n"
154 		"",
155 		argv[0], FLASHROM_PROGRAMMER_INTERNAL_AP);
156 }
157 
do_update(int argc,char * argv[])158 static int do_update(int argc, char *argv[])
159 {
160 	struct updater_config_arguments args = {0};
161 	int i, errorcnt = 0;
162 	const char *prepare_ctrl_name = NULL;
163 	char *servo_programmer = NULL;
164 	char *endptr;
165 	const char *sig = NULL;
166 
167 	struct updater_config *cfg = updater_new_config();
168 	assert(cfg);
169 
170 	opterr = 0;
171 	while ((i = getopt_long(argc, argv, short_opts, long_opts, 0)) != -1) {
172 		if (handle_flash_argument(&args, i, optarg))
173 			continue;
174 		switch (i) {
175 		case 'h':
176 			print_help(argc, argv);
177 			updater_delete_config(cfg);
178 			return !!errorcnt;
179 		case 'd':
180 			debugging_enabled = 1;
181 			args.verbosity++;
182 			break;
183 		case 'v':
184 			args.verbosity++;
185 			break;
186 		case 'i':
187 			args.image = optarg;
188 			break;
189 		case 'e':
190 			args.ec_image = optarg;
191 			break;
192 		case 't':
193 			args.try_update = 1;
194 			break;
195 		case 'a':
196 			args.archive = optarg;
197 			break;
198 		case 'm':
199 			args.mode = optarg;
200 			break;
201 
202 		case OPT_REPACK:
203 			args.repack = optarg;
204 			ERROR("Sorry, --repack is only for the script.\n");
205 			errorcnt ++;
206 			break;
207 		case OPT_UNPACK:
208 			args.unpack = optarg;
209 			break;
210 		case OPT_UNLOCK_ME:
211 			WARN("--unlock_me will be deprecated by --quirks unlock_csme.\n");
212 			args.unlock_me = true;
213 			break;
214 		case OPT_QUIRKS:
215 			args.quirks = optarg;
216 			break;
217 		case OPT_QUIRKS_LIST:
218 			updater_list_config_quirks(cfg);
219 			updater_delete_config(cfg);
220 			return 0;
221 		case OPT_OUTPUT_DIR:
222 			args.output_dir = optarg;
223 			break;
224 		case OPT_MODEL:
225 			if (sig) {
226 				WARN("Ignore --model=%s because --signature_id=%s is already specified.\n", optarg, sig);
227 			} else {
228 				args.model = optarg;
229 			}
230 			break;
231 		case OPT_SIGNATURE:
232 			WARN("--signature_id is deprecated by --model. "
233 			      "Please change to `--model=%s` in future.\n",
234 			      optarg);
235 			sig = optarg;
236 			args.model = optarg;
237 			break;
238 		case OPT_DETECT_MODEL_ONLY:
239 			args.detect_model_only = true;
240 			break;
241 		case OPT_WRITE_PROTECTION:
242 			args.write_protection = optarg;
243 			break;
244 		case OPT_SYS_PROPS:
245 			args.sys_props = optarg;
246 			break;
247 		case OPT_MANIFEST:
248 			args.do_manifest = 1;
249 			args.manifest_format = MANIFEST_PRINT_FORMAT_JSON;
250 			break;
251 		case OPT_PARSEABLE_MANIFEST:
252 			args.do_manifest = 1;
253 			args.manifest_format = MANIFEST_PRINT_FORMAT_PARSEABLE;
254 			break;
255 		case OPT_FACTORY:
256 			args.is_factory = 1;
257 			break;
258 		case OPT_HOST_ONLY:
259 			args.host_only = 1;
260 			break;
261 		case OPT_FORCE:
262 			args.force_update = 1;
263 			break;
264 		case OPT_FAST:
265 			args.fast_update = 1;
266 			break;
267 		case OPT_GBB_FLAGS:
268 			args.gbb_flags = strtoul(optarg, &endptr, 0);
269 			if (*endptr) {
270 				ERROR("Invalid flags: %s\n", optarg);
271 				errorcnt++;
272 			} else {
273 				args.override_gbb_flags = 1;
274 			}
275 			break;
276 		case OPT_DUMMY:
277 			break;
278 
279 		case '?':
280 			errorcnt++;
281 			if (optopt)
282 				ERROR("Unrecognized option: -%c\n", optopt);
283 			else if (argv[optind - 1])
284 				ERROR("Unrecognized option (possibly '%s')\n",
285 				      argv[optind - 1]);
286 			else
287 				ERROR("Unrecognized option.\n");
288 			break;
289 		default:
290 			errorcnt++;
291 			ERROR("Failed parsing options.\n");
292 		}
293 	}
294 	if (optind < argc) {
295 		errorcnt++;
296 		ERROR("Unexpected arguments.\n");
297 	}
298 
299 	if (!errorcnt && args.detect_servo) {
300 		servo_programmer = host_detect_servo(&prepare_ctrl_name);
301 
302 		if (!servo_programmer)
303 			errorcnt++;
304 		else if (!args.programmer)
305 			args.programmer = servo_programmer;
306 	}
307 	/*
308 	 * Some boards may need to fetch firmware before starting to
309 	 * update (i.e., in updater_setup_config) so we want to turn on
310 	 * cpu_fw_spi mode now.
311 	 */
312 	prepare_servo_control(prepare_ctrl_name, true);
313 
314 	const bool update_needed = updater_should_update(&args);
315 	if (!errorcnt)
316 		errorcnt += updater_setup_config(cfg, &args);
317 	if (!errorcnt && update_needed) {
318 		int r;
319 		STATUS("Starting firmware updater.\n");
320 		r = update_firmware(cfg);
321 		if (r != UPDATE_ERR_DONE) {
322 			r = VB2_MIN(r, UPDATE_ERR_UNKNOWN);
323 			ERROR("%s\n", updater_error_messages[r]);
324 			errorcnt++;
325 		}
326 		/* Use stdout for the final result. */
327 		printf(">> %s: Firmware updater %s.\n",
328 			errorcnt ? "FAILED": "DONE",
329 			errorcnt ? "aborted" : "exits successfully");
330 	}
331 
332 	prepare_servo_control(prepare_ctrl_name, false);
333 	free(servo_programmer);
334 
335 	updater_delete_config(cfg);
336 	return !!errorcnt;
337 }
338 #define CMD_HELP_STR "Update system firmware"
339 
340 #else /* USE_FLASHROM */
341 
do_update(int argc,char * argv[])342 static int do_update(int argc, char *argv[])
343 {
344 	FATAL(MYNAME " was built without flashrom support, `update` command unavailable!\n");
345 	return -1;
346 }
347 #define CMD_HELP_STR "Update system firmware (unavailable in this build)"
348 
349 #endif /* !USE_FLASHROM */
350 
351 DECLARE_FUTIL_COMMAND(update, do_update, VBOOT_VERSION_ALL, CMD_HELP_STR);
352