xref: /aosp_15_r20/external/vboot_reference/futility/futility.c (revision 8617a60d3594060b7ecbd21bc622a7c14f3cf2bc)
1*8617a60dSAndroid Build Coastguard Worker /* Copyright 2013 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 <fcntl.h>
8*8617a60dSAndroid Build Coastguard Worker #include <getopt.h>
9*8617a60dSAndroid Build Coastguard Worker #include <limits.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 <unistd.h>
16*8617a60dSAndroid Build Coastguard Worker 
17*8617a60dSAndroid Build Coastguard Worker #include "futility.h"
18*8617a60dSAndroid Build Coastguard Worker 
19*8617a60dSAndroid Build Coastguard Worker const char *ft_print_header = NULL;
20*8617a60dSAndroid Build Coastguard Worker const char *ft_print_header2 = NULL;
21*8617a60dSAndroid Build Coastguard Worker 
22*8617a60dSAndroid Build Coastguard Worker /******************************************************************************/
23*8617a60dSAndroid Build Coastguard Worker 
24*8617a60dSAndroid Build Coastguard Worker static const char *const usage = "\n"
25*8617a60dSAndroid Build Coastguard Worker "Usage: " MYNAME " [options] COMMAND [args...]\n"
26*8617a60dSAndroid Build Coastguard Worker "\n"
27*8617a60dSAndroid Build Coastguard Worker "This is the unified firmware utility, which contains various of distinct\n"
28*8617a60dSAndroid Build Coastguard Worker "verified boot tools as subcommands.\n"
29*8617a60dSAndroid Build Coastguard Worker "\n"
30*8617a60dSAndroid Build Coastguard Worker "See the README file for more information about the available commands\n";
31*8617a60dSAndroid Build Coastguard Worker 
32*8617a60dSAndroid Build Coastguard Worker static const char *const options =
33*8617a60dSAndroid Build Coastguard Worker "Global options:\n"
34*8617a60dSAndroid Build Coastguard Worker "\n"
35*8617a60dSAndroid Build Coastguard Worker "  --vb1        Use only vboot v1.0 binary formats\n"
36*8617a60dSAndroid Build Coastguard Worker "  --vb21       Use only vboot v2.1 binary formats\n"
37*8617a60dSAndroid Build Coastguard Worker "  --debug      Be noisy about what's going on\n"
38*8617a60dSAndroid Build Coastguard Worker "\n";
39*8617a60dSAndroid Build Coastguard Worker 
find_command(const char * name)40*8617a60dSAndroid Build Coastguard Worker static const struct futil_cmd_t *find_command(const char *name)
41*8617a60dSAndroid Build Coastguard Worker {
42*8617a60dSAndroid Build Coastguard Worker 	const struct futil_cmd_t *const *cmd;
43*8617a60dSAndroid Build Coastguard Worker 
44*8617a60dSAndroid Build Coastguard Worker 	for (cmd = futil_cmds; *cmd; cmd++)
45*8617a60dSAndroid Build Coastguard Worker 		if (((*cmd)->version & vboot_version) &&
46*8617a60dSAndroid Build Coastguard Worker 		    !strcmp((*cmd)->name, name))
47*8617a60dSAndroid Build Coastguard Worker 			return *cmd;
48*8617a60dSAndroid Build Coastguard Worker 
49*8617a60dSAndroid Build Coastguard Worker 	return NULL;
50*8617a60dSAndroid Build Coastguard Worker }
51*8617a60dSAndroid Build Coastguard Worker 
list_commands(void)52*8617a60dSAndroid Build Coastguard Worker static void list_commands(void)
53*8617a60dSAndroid Build Coastguard Worker {
54*8617a60dSAndroid Build Coastguard Worker 	const struct futil_cmd_t *const *cmd;
55*8617a60dSAndroid Build Coastguard Worker 
56*8617a60dSAndroid Build Coastguard Worker 	for (cmd = futil_cmds; *cmd; cmd++)
57*8617a60dSAndroid Build Coastguard Worker 		if (vboot_version & (*cmd)->version)
58*8617a60dSAndroid Build Coastguard Worker 			printf("  %-20s %s\n",
59*8617a60dSAndroid Build Coastguard Worker 			       (*cmd)->name, (*cmd)->shorthelp);
60*8617a60dSAndroid Build Coastguard Worker }
61*8617a60dSAndroid Build Coastguard Worker 
run_command(const struct futil_cmd_t * cmd,int argc,char * argv[])62*8617a60dSAndroid Build Coastguard Worker static int run_command(const struct futil_cmd_t *cmd, int argc, char *argv[])
63*8617a60dSAndroid Build Coastguard Worker {
64*8617a60dSAndroid Build Coastguard Worker 	int i;
65*8617a60dSAndroid Build Coastguard Worker 	VB2_DEBUG("\"%s\" ...\n", cmd->name);
66*8617a60dSAndroid Build Coastguard Worker 	for (i = 0; i < argc; i++)
67*8617a60dSAndroid Build Coastguard Worker 		VB2_DEBUG("  argv[%d] = \"%s\"\n", i, argv[i]);
68*8617a60dSAndroid Build Coastguard Worker 
69*8617a60dSAndroid Build Coastguard Worker 	return cmd->handler(argc, argv);
70*8617a60dSAndroid Build Coastguard Worker }
71*8617a60dSAndroid Build Coastguard Worker 
do_help(int argc,char * argv[])72*8617a60dSAndroid Build Coastguard Worker static int do_help(int argc, char *argv[])
73*8617a60dSAndroid Build Coastguard Worker {
74*8617a60dSAndroid Build Coastguard Worker 	const struct futil_cmd_t *cmd;
75*8617a60dSAndroid Build Coastguard Worker 	const char *vstr = "";
76*8617a60dSAndroid Build Coastguard Worker 
77*8617a60dSAndroid Build Coastguard Worker 	/* Help about a known command? */
78*8617a60dSAndroid Build Coastguard Worker 	if (argc > 1) {
79*8617a60dSAndroid Build Coastguard Worker 		cmd = find_command(argv[1]);
80*8617a60dSAndroid Build Coastguard Worker 		if (cmd) {
81*8617a60dSAndroid Build Coastguard Worker 			/* Let the command provide its own help */
82*8617a60dSAndroid Build Coastguard Worker 			argv[0] = argv[1];
83*8617a60dSAndroid Build Coastguard Worker 			argv[1] = (char *)"--help";
84*8617a60dSAndroid Build Coastguard Worker 			return run_command(cmd, argc, argv);
85*8617a60dSAndroid Build Coastguard Worker 		}
86*8617a60dSAndroid Build Coastguard Worker 	}
87*8617a60dSAndroid Build Coastguard Worker 
88*8617a60dSAndroid Build Coastguard Worker 	fputs(usage, stdout);
89*8617a60dSAndroid Build Coastguard Worker 
90*8617a60dSAndroid Build Coastguard Worker 	if (vboot_version == VBOOT_VERSION_ALL)
91*8617a60dSAndroid Build Coastguard Worker 		fputs(options, stdout);
92*8617a60dSAndroid Build Coastguard Worker 
93*8617a60dSAndroid Build Coastguard Worker 	switch (vboot_version) {
94*8617a60dSAndroid Build Coastguard Worker 	case VBOOT_VERSION_1_0:
95*8617a60dSAndroid Build Coastguard Worker 		vstr = "version 1.0 ";
96*8617a60dSAndroid Build Coastguard Worker 		break;
97*8617a60dSAndroid Build Coastguard Worker 	case VBOOT_VERSION_2_1:
98*8617a60dSAndroid Build Coastguard Worker 		vstr = "version 2.1 ";
99*8617a60dSAndroid Build Coastguard Worker 		break;
100*8617a60dSAndroid Build Coastguard Worker 	case VBOOT_VERSION_ALL:
101*8617a60dSAndroid Build Coastguard Worker 		vstr = "";
102*8617a60dSAndroid Build Coastguard Worker 		break;
103*8617a60dSAndroid Build Coastguard Worker 	}
104*8617a60dSAndroid Build Coastguard Worker 	printf("The following %scommands are built-in:\n\n", vstr);
105*8617a60dSAndroid Build Coastguard Worker 	list_commands();
106*8617a60dSAndroid Build Coastguard Worker 	printf("\nUse \"" MYNAME " help COMMAND\" for more information.\n\n");
107*8617a60dSAndroid Build Coastguard Worker 
108*8617a60dSAndroid Build Coastguard Worker 	return 0;
109*8617a60dSAndroid Build Coastguard Worker }
110*8617a60dSAndroid Build Coastguard Worker 
111*8617a60dSAndroid Build Coastguard Worker DECLARE_FUTIL_COMMAND(help, do_help, VBOOT_VERSION_ALL,
112*8617a60dSAndroid Build Coastguard Worker 		      "Show a bit of help (you're looking at it)");
113*8617a60dSAndroid Build Coastguard Worker 
114*8617a60dSAndroid Build Coastguard Worker static const char ver_help[] =
115*8617a60dSAndroid Build Coastguard Worker 	"Show the futility source revision and build date";
do_version(int argc,char * argv[])116*8617a60dSAndroid Build Coastguard Worker static int do_version(int argc, char *argv[])
117*8617a60dSAndroid Build Coastguard Worker {
118*8617a60dSAndroid Build Coastguard Worker 	if (argc > 1)
119*8617a60dSAndroid Build Coastguard Worker 		printf("%s - %s\n", argv[0], ver_help);
120*8617a60dSAndroid Build Coastguard Worker 	else
121*8617a60dSAndroid Build Coastguard Worker 		printf("%s\n", futility_version);
122*8617a60dSAndroid Build Coastguard Worker 	return 0;
123*8617a60dSAndroid Build Coastguard Worker }
124*8617a60dSAndroid Build Coastguard Worker 
125*8617a60dSAndroid Build Coastguard Worker DECLARE_FUTIL_COMMAND(version, do_version, VBOOT_VERSION_ALL,
126*8617a60dSAndroid Build Coastguard Worker 		      ver_help);
127*8617a60dSAndroid Build Coastguard Worker 
simple_basename(char * str)128*8617a60dSAndroid Build Coastguard Worker static char *simple_basename(char *str)
129*8617a60dSAndroid Build Coastguard Worker {
130*8617a60dSAndroid Build Coastguard Worker 	char *s = strrchr(str, '/');
131*8617a60dSAndroid Build Coastguard Worker 	if (s)
132*8617a60dSAndroid Build Coastguard Worker 		s++;
133*8617a60dSAndroid Build Coastguard Worker 	else
134*8617a60dSAndroid Build Coastguard Worker 		s = str;
135*8617a60dSAndroid Build Coastguard Worker 	return s;
136*8617a60dSAndroid Build Coastguard Worker }
137*8617a60dSAndroid Build Coastguard Worker 
138*8617a60dSAndroid Build Coastguard Worker /* Here we go */
139*8617a60dSAndroid Build Coastguard Worker #define OPT_HELP 1000
140*8617a60dSAndroid Build Coastguard Worker test_mockable
main(int argc,char * argv[],char * envp[])141*8617a60dSAndroid Build Coastguard Worker int main(int argc, char *argv[], char *envp[])
142*8617a60dSAndroid Build Coastguard Worker {
143*8617a60dSAndroid Build Coastguard Worker 	char *progname;
144*8617a60dSAndroid Build Coastguard Worker 	const struct futil_cmd_t *cmd;
145*8617a60dSAndroid Build Coastguard Worker 	int i, errorcnt = 0;
146*8617a60dSAndroid Build Coastguard Worker 	int vb_ver = VBOOT_VERSION_ALL;
147*8617a60dSAndroid Build Coastguard Worker 	int helpind = 0;
148*8617a60dSAndroid Build Coastguard Worker 	struct option long_opts[] = {
149*8617a60dSAndroid Build Coastguard Worker 		{"debug", 0, &debugging_enabled, 1},
150*8617a60dSAndroid Build Coastguard Worker 		{"vb1" ,  0, &vb_ver, VBOOT_VERSION_1_0},
151*8617a60dSAndroid Build Coastguard Worker 		{"vb21",  0, &vb_ver, VBOOT_VERSION_2_1},
152*8617a60dSAndroid Build Coastguard Worker 		{"help",  0, 0, OPT_HELP},
153*8617a60dSAndroid Build Coastguard Worker 		{ 0, 0, 0, 0},
154*8617a60dSAndroid Build Coastguard Worker 	};
155*8617a60dSAndroid Build Coastguard Worker 
156*8617a60dSAndroid Build Coastguard Worker 	/* How were we invoked? */
157*8617a60dSAndroid Build Coastguard Worker 	progname = simple_basename(argv[0]);
158*8617a60dSAndroid Build Coastguard Worker 
159*8617a60dSAndroid Build Coastguard Worker 	/* See if the program name is a command we recognize */
160*8617a60dSAndroid Build Coastguard Worker 	cmd = find_command(progname);
161*8617a60dSAndroid Build Coastguard Worker 	if (cmd) {
162*8617a60dSAndroid Build Coastguard Worker 		/* Yep, just do that */
163*8617a60dSAndroid Build Coastguard Worker 		return !!run_command(cmd, argc, argv);
164*8617a60dSAndroid Build Coastguard Worker 	}
165*8617a60dSAndroid Build Coastguard Worker 
166*8617a60dSAndroid Build Coastguard Worker 	/* Parse the global options, stopping at the first non-option. */
167*8617a60dSAndroid Build Coastguard Worker 	opterr = 0;				/* quiet, you. */
168*8617a60dSAndroid Build Coastguard Worker 	while ((i = getopt_long(argc, argv, "+:", long_opts, NULL)) != -1) {
169*8617a60dSAndroid Build Coastguard Worker 		switch (i) {
170*8617a60dSAndroid Build Coastguard Worker 		case OPT_HELP:
171*8617a60dSAndroid Build Coastguard Worker 			/* Remember where we found this option */
172*8617a60dSAndroid Build Coastguard Worker 			/* Note: this might be GNU-specific */
173*8617a60dSAndroid Build Coastguard Worker 			helpind = optind - 1;
174*8617a60dSAndroid Build Coastguard Worker 			break;
175*8617a60dSAndroid Build Coastguard Worker 		case '?':
176*8617a60dSAndroid Build Coastguard Worker 			if (optopt)
177*8617a60dSAndroid Build Coastguard Worker 				fprintf(stderr, "Unrecognized option: -%c\n",
178*8617a60dSAndroid Build Coastguard Worker 					optopt);
179*8617a60dSAndroid Build Coastguard Worker 			else
180*8617a60dSAndroid Build Coastguard Worker 				fprintf(stderr, "Unrecognized option: %s\n",
181*8617a60dSAndroid Build Coastguard Worker 					argv[optind - 1]);
182*8617a60dSAndroid Build Coastguard Worker 			errorcnt++;
183*8617a60dSAndroid Build Coastguard Worker 			break;
184*8617a60dSAndroid Build Coastguard Worker 		case ':':
185*8617a60dSAndroid Build Coastguard Worker 			fprintf(stderr, "Missing argument to -%c\n", optopt);
186*8617a60dSAndroid Build Coastguard Worker 			errorcnt++;
187*8617a60dSAndroid Build Coastguard Worker 			break;
188*8617a60dSAndroid Build Coastguard Worker 		case 0:				/* handled option */
189*8617a60dSAndroid Build Coastguard Worker 			break;
190*8617a60dSAndroid Build Coastguard Worker 		default:
191*8617a60dSAndroid Build Coastguard Worker 			FATAL("Unrecognized getopt output: %d\n", i);
192*8617a60dSAndroid Build Coastguard Worker 		}
193*8617a60dSAndroid Build Coastguard Worker 	}
194*8617a60dSAndroid Build Coastguard Worker 	vboot_version = vb_ver;
195*8617a60dSAndroid Build Coastguard Worker 
196*8617a60dSAndroid Build Coastguard Worker 	/*
197*8617a60dSAndroid Build Coastguard Worker 	 * Translate "--help" in the args to "help" as the first parameter,
198*8617a60dSAndroid Build Coastguard Worker 	 * by rearranging argv[].
199*8617a60dSAndroid Build Coastguard Worker 	 */
200*8617a60dSAndroid Build Coastguard Worker 	if (helpind) {
201*8617a60dSAndroid Build Coastguard Worker 		int j;
202*8617a60dSAndroid Build Coastguard Worker 		optind--;
203*8617a60dSAndroid Build Coastguard Worker 		for (j = helpind; j < optind; j++)
204*8617a60dSAndroid Build Coastguard Worker 			argv[j] = argv[j + 1];
205*8617a60dSAndroid Build Coastguard Worker 		argv[j] = (char *)"help";
206*8617a60dSAndroid Build Coastguard Worker 	}
207*8617a60dSAndroid Build Coastguard Worker 
208*8617a60dSAndroid Build Coastguard Worker 	/* We require a command name. */
209*8617a60dSAndroid Build Coastguard Worker 	if (errorcnt || argc == optind) {
210*8617a60dSAndroid Build Coastguard Worker 		do_help(1, argv);
211*8617a60dSAndroid Build Coastguard Worker 		return 1;
212*8617a60dSAndroid Build Coastguard Worker 	}
213*8617a60dSAndroid Build Coastguard Worker 
214*8617a60dSAndroid Build Coastguard Worker 	/* For reasons I've forgotten, treat /blah/blah/CMD the same as CMD */
215*8617a60dSAndroid Build Coastguard Worker 	argv[optind] = simple_basename(argv[optind]);
216*8617a60dSAndroid Build Coastguard Worker 
217*8617a60dSAndroid Build Coastguard Worker 	/* Do we recognize the command? */
218*8617a60dSAndroid Build Coastguard Worker 	cmd = find_command(argv[optind]);
219*8617a60dSAndroid Build Coastguard Worker 	if (cmd) {
220*8617a60dSAndroid Build Coastguard Worker 		/* Reset so commands can parse their own options */
221*8617a60dSAndroid Build Coastguard Worker 		argc -= optind;
222*8617a60dSAndroid Build Coastguard Worker 		argv += optind;
223*8617a60dSAndroid Build Coastguard Worker 		optind = 0;
224*8617a60dSAndroid Build Coastguard Worker 		return !!run_command(cmd, argc, argv);
225*8617a60dSAndroid Build Coastguard Worker 	}
226*8617a60dSAndroid Build Coastguard Worker 
227*8617a60dSAndroid Build Coastguard Worker 	/* Nope. We've no clue what we're being asked to do. */
228*8617a60dSAndroid Build Coastguard Worker 	do_help(1, argv);
229*8617a60dSAndroid Build Coastguard Worker 	return 1;
230*8617a60dSAndroid Build Coastguard Worker }
231