xref: /OK3568_Linux_fs/u-boot/tools/env/fw_env_main.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * (C) Copyright 2000-2008
3*4882a593Smuzhiyun  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * SPDX-License-Identifier:	GPL-2.0+
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun /*
9*4882a593Smuzhiyun  * Command line user interface to firmware (=U-Boot) environment.
10*4882a593Smuzhiyun  *
11*4882a593Smuzhiyun  * Implements:
12*4882a593Smuzhiyun  *	fw_printenv [ -a key ] [[ -n name ] | [ name ... ]]
13*4882a593Smuzhiyun  *              - prints the value of a single environment variable
14*4882a593Smuzhiyun  *                "name", the ``name=value'' pairs of one or more
15*4882a593Smuzhiyun  *                environment variables "name", or the whole
16*4882a593Smuzhiyun  *                environment if no names are specified.
17*4882a593Smuzhiyun  *	fw_setenv [ -a key ] name [ value ... ]
18*4882a593Smuzhiyun  *		- If a name without any values is given, the variable
19*4882a593Smuzhiyun  *		  with this name is deleted from the environment;
20*4882a593Smuzhiyun  *		  otherwise, all "value" arguments are concatenated,
21*4882a593Smuzhiyun  *		  separated by single blank characters, and the
22*4882a593Smuzhiyun  *		  resulting string is assigned to the environment
23*4882a593Smuzhiyun  *		  variable "name"
24*4882a593Smuzhiyun  *
25*4882a593Smuzhiyun  * If '-a key' is specified, the env block is encrypted with AES 128 CBC.
26*4882a593Smuzhiyun  * The 'key' argument is in the format of 32 hexadecimal numbers (16 bytes
27*4882a593Smuzhiyun  * of AES key), eg. '-a aabbccddeeff00112233445566778899'.
28*4882a593Smuzhiyun  */
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun #include <fcntl.h>
31*4882a593Smuzhiyun #include <getopt.h>
32*4882a593Smuzhiyun #include <stdio.h>
33*4882a593Smuzhiyun #include <string.h>
34*4882a593Smuzhiyun #include <stdlib.h>
35*4882a593Smuzhiyun #include <sys/file.h>
36*4882a593Smuzhiyun #include <unistd.h>
37*4882a593Smuzhiyun #include <version.h>
38*4882a593Smuzhiyun #include "fw_env_private.h"
39*4882a593Smuzhiyun #include "fw_env.h"
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun #define CMD_PRINTENV	"fw_printenv"
42*4882a593Smuzhiyun #define CMD_SETENV	"fw_setenv"
43*4882a593Smuzhiyun static int do_printenv;
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun static struct option long_options[] = {
46*4882a593Smuzhiyun 	{"aes", required_argument, NULL, 'a'},
47*4882a593Smuzhiyun 	{"config", required_argument, NULL, 'c'},
48*4882a593Smuzhiyun 	{"help", no_argument, NULL, 'h'},
49*4882a593Smuzhiyun 	{"script", required_argument, NULL, 's'},
50*4882a593Smuzhiyun 	{"noheader", required_argument, NULL, 'n'},
51*4882a593Smuzhiyun 	{"lock", required_argument, NULL, 'l'},
52*4882a593Smuzhiyun 	{"version", no_argument, NULL, 'v'},
53*4882a593Smuzhiyun 	{NULL, 0, NULL, 0}
54*4882a593Smuzhiyun };
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun static struct env_opts env_opts;
57*4882a593Smuzhiyun 
58*4882a593Smuzhiyun /* setenv options */
59*4882a593Smuzhiyun static int noheader;
60*4882a593Smuzhiyun 
61*4882a593Smuzhiyun /* getenv options */
62*4882a593Smuzhiyun static char *script_file;
63*4882a593Smuzhiyun 
usage_printenv(void)64*4882a593Smuzhiyun void usage_printenv(void)
65*4882a593Smuzhiyun {
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun 	fprintf(stderr,
68*4882a593Smuzhiyun 		"Usage: fw_printenv [OPTIONS]... [VARIABLE]...\n"
69*4882a593Smuzhiyun 		"Print variables from U-Boot environment\n"
70*4882a593Smuzhiyun 		"\n"
71*4882a593Smuzhiyun 		" -h, --help           print this help.\n"
72*4882a593Smuzhiyun 		" -v, --version        display version\n"
73*4882a593Smuzhiyun #ifdef CONFIG_ENV_AES
74*4882a593Smuzhiyun 		" -a, --aes            aes key to access environment\n"
75*4882a593Smuzhiyun #endif
76*4882a593Smuzhiyun #ifdef CONFIG_FILE
77*4882a593Smuzhiyun 		" -c, --config         configuration file, default:" CONFIG_FILE "\n"
78*4882a593Smuzhiyun #endif
79*4882a593Smuzhiyun 		" -n, --noheader       do not repeat variable name in output\n"
80*4882a593Smuzhiyun 		" -l, --lock           lock node, default:/var/lock\n"
81*4882a593Smuzhiyun 		"\n");
82*4882a593Smuzhiyun }
83*4882a593Smuzhiyun 
usage_env_set(void)84*4882a593Smuzhiyun void usage_env_set(void)
85*4882a593Smuzhiyun {
86*4882a593Smuzhiyun 	fprintf(stderr,
87*4882a593Smuzhiyun 		"Usage: fw_setenv [OPTIONS]... [VARIABLE]...\n"
88*4882a593Smuzhiyun 		"Modify variables in U-Boot environment\n"
89*4882a593Smuzhiyun 		"\n"
90*4882a593Smuzhiyun 		" -h, --help           print this help.\n"
91*4882a593Smuzhiyun 		" -v, --version        display version\n"
92*4882a593Smuzhiyun #ifdef CONFIG_ENV_AES
93*4882a593Smuzhiyun 		" -a, --aes            aes key to access environment\n"
94*4882a593Smuzhiyun #endif
95*4882a593Smuzhiyun #ifdef CONFIG_FILE
96*4882a593Smuzhiyun 		" -c, --config         configuration file, default:" CONFIG_FILE "\n"
97*4882a593Smuzhiyun #endif
98*4882a593Smuzhiyun 		" -l, --lock           lock node, default:/var/lock\n"
99*4882a593Smuzhiyun 		" -s, --script         batch mode to minimize writes\n"
100*4882a593Smuzhiyun 		"\n"
101*4882a593Smuzhiyun 		"Examples:\n"
102*4882a593Smuzhiyun 		"  fw_setenv foo bar   set variable foo equal bar\n"
103*4882a593Smuzhiyun 		"  fw_setenv foo       clear variable foo\n"
104*4882a593Smuzhiyun 		"  fw_setenv --script file run batch script\n"
105*4882a593Smuzhiyun 		"\n"
106*4882a593Smuzhiyun 		"Script Syntax:\n"
107*4882a593Smuzhiyun 		"  key [space] value\n"
108*4882a593Smuzhiyun 		"  lines starting with '#' are treated as comment\n"
109*4882a593Smuzhiyun 		"\n"
110*4882a593Smuzhiyun 		"  A variable without value will be deleted. Any number of spaces are\n"
111*4882a593Smuzhiyun 		"  allowed between key and value. Space inside of the value is treated\n"
112*4882a593Smuzhiyun 		"  as part of the value itself.\n"
113*4882a593Smuzhiyun 		"\n"
114*4882a593Smuzhiyun 		"Script Example:\n"
115*4882a593Smuzhiyun 		"  netdev         eth0\n"
116*4882a593Smuzhiyun 		"  kernel_addr    400000\n"
117*4882a593Smuzhiyun 		"  foo            empty empty empty    empty empty empty\n"
118*4882a593Smuzhiyun 		"  bar\n"
119*4882a593Smuzhiyun 		"\n");
120*4882a593Smuzhiyun }
121*4882a593Smuzhiyun 
parse_common_args(int argc,char * argv[])122*4882a593Smuzhiyun static void parse_common_args(int argc, char *argv[])
123*4882a593Smuzhiyun {
124*4882a593Smuzhiyun 	int c;
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun #ifdef CONFIG_FILE
127*4882a593Smuzhiyun 	env_opts.config_file = CONFIG_FILE;
128*4882a593Smuzhiyun #endif
129*4882a593Smuzhiyun 
130*4882a593Smuzhiyun 	while ((c = getopt_long(argc, argv, ":a:c:l:h:v", long_options, NULL)) !=
131*4882a593Smuzhiyun 	       EOF) {
132*4882a593Smuzhiyun 		switch (c) {
133*4882a593Smuzhiyun 		case 'a':
134*4882a593Smuzhiyun 			if (parse_aes_key(optarg, env_opts.aes_key)) {
135*4882a593Smuzhiyun 				fprintf(stderr, "AES key parse error\n");
136*4882a593Smuzhiyun 				exit(EXIT_FAILURE);
137*4882a593Smuzhiyun 			}
138*4882a593Smuzhiyun 			env_opts.aes_flag = 1;
139*4882a593Smuzhiyun 			break;
140*4882a593Smuzhiyun #ifdef CONFIG_FILE
141*4882a593Smuzhiyun 		case 'c':
142*4882a593Smuzhiyun 			env_opts.config_file = optarg;
143*4882a593Smuzhiyun 			break;
144*4882a593Smuzhiyun #endif
145*4882a593Smuzhiyun 		case 'l':
146*4882a593Smuzhiyun 			env_opts.lockname = optarg;
147*4882a593Smuzhiyun 			break;
148*4882a593Smuzhiyun 		case 'h':
149*4882a593Smuzhiyun 			do_printenv ? usage_printenv() : usage_env_set();
150*4882a593Smuzhiyun 			exit(EXIT_SUCCESS);
151*4882a593Smuzhiyun 			break;
152*4882a593Smuzhiyun 		case 'v':
153*4882a593Smuzhiyun 			fprintf(stderr, "Compiled with " U_BOOT_VERSION "\n");
154*4882a593Smuzhiyun 			exit(EXIT_SUCCESS);
155*4882a593Smuzhiyun 			break;
156*4882a593Smuzhiyun 		default:
157*4882a593Smuzhiyun 			/* ignore unknown options */
158*4882a593Smuzhiyun 			break;
159*4882a593Smuzhiyun 		}
160*4882a593Smuzhiyun 	}
161*4882a593Smuzhiyun 
162*4882a593Smuzhiyun 	/* Reset getopt for the next pass. */
163*4882a593Smuzhiyun 	opterr = 1;
164*4882a593Smuzhiyun 	optind = 1;
165*4882a593Smuzhiyun }
166*4882a593Smuzhiyun 
parse_printenv_args(int argc,char * argv[])167*4882a593Smuzhiyun int parse_printenv_args(int argc, char *argv[])
168*4882a593Smuzhiyun {
169*4882a593Smuzhiyun 	int c;
170*4882a593Smuzhiyun 
171*4882a593Smuzhiyun 	parse_common_args(argc, argv);
172*4882a593Smuzhiyun 
173*4882a593Smuzhiyun 	while ((c = getopt_long(argc, argv, "a:c:ns:l:h:v", long_options, NULL))
174*4882a593Smuzhiyun 		!= EOF) {
175*4882a593Smuzhiyun 		switch (c) {
176*4882a593Smuzhiyun 		case 'n':
177*4882a593Smuzhiyun 			noheader = 1;
178*4882a593Smuzhiyun 			break;
179*4882a593Smuzhiyun 		case 'a':
180*4882a593Smuzhiyun 		case 'c':
181*4882a593Smuzhiyun 		case 'h':
182*4882a593Smuzhiyun 		case 'l':
183*4882a593Smuzhiyun 			/* ignore common options */
184*4882a593Smuzhiyun 			break;
185*4882a593Smuzhiyun 		default: /* '?' */
186*4882a593Smuzhiyun 			usage_printenv();
187*4882a593Smuzhiyun 			exit(EXIT_FAILURE);
188*4882a593Smuzhiyun 			break;
189*4882a593Smuzhiyun 		}
190*4882a593Smuzhiyun 	}
191*4882a593Smuzhiyun 	return 0;
192*4882a593Smuzhiyun }
193*4882a593Smuzhiyun 
parse_setenv_args(int argc,char * argv[])194*4882a593Smuzhiyun int parse_setenv_args(int argc, char *argv[])
195*4882a593Smuzhiyun {
196*4882a593Smuzhiyun 	int c;
197*4882a593Smuzhiyun 
198*4882a593Smuzhiyun 	parse_common_args(argc, argv);
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun 	while ((c = getopt_long(argc, argv, "a:c:ns:l:h:v", long_options, NULL))
201*4882a593Smuzhiyun 		!= EOF) {
202*4882a593Smuzhiyun 		switch (c) {
203*4882a593Smuzhiyun 		case 's':
204*4882a593Smuzhiyun 			script_file = optarg;
205*4882a593Smuzhiyun 			break;
206*4882a593Smuzhiyun 		case 'a':
207*4882a593Smuzhiyun 		case 'c':
208*4882a593Smuzhiyun 		case 'h':
209*4882a593Smuzhiyun 		case 'l':
210*4882a593Smuzhiyun 			/* ignore common options */
211*4882a593Smuzhiyun 			break;
212*4882a593Smuzhiyun 		default: /* '?' */
213*4882a593Smuzhiyun 			usage_env_set();
214*4882a593Smuzhiyun 			exit(EXIT_FAILURE);
215*4882a593Smuzhiyun 			break;
216*4882a593Smuzhiyun 		}
217*4882a593Smuzhiyun 	}
218*4882a593Smuzhiyun 	return 0;
219*4882a593Smuzhiyun }
220*4882a593Smuzhiyun 
main(int argc,char * argv[])221*4882a593Smuzhiyun int main(int argc, char *argv[])
222*4882a593Smuzhiyun {
223*4882a593Smuzhiyun 	char *lockname = "/var/lock/" CMD_PRINTENV ".lock";
224*4882a593Smuzhiyun 	int lockfd = -1;
225*4882a593Smuzhiyun 	int retval = EXIT_SUCCESS;
226*4882a593Smuzhiyun 	char *_cmdname;
227*4882a593Smuzhiyun 
228*4882a593Smuzhiyun 	_cmdname = *argv;
229*4882a593Smuzhiyun 	if (strrchr(_cmdname, '/') != NULL)
230*4882a593Smuzhiyun 		_cmdname = strrchr(_cmdname, '/') + 1;
231*4882a593Smuzhiyun 
232*4882a593Smuzhiyun 	if (strcmp(_cmdname, CMD_PRINTENV) == 0) {
233*4882a593Smuzhiyun 		do_printenv = 1;
234*4882a593Smuzhiyun 	} else if (strcmp(_cmdname, CMD_SETENV) == 0) {
235*4882a593Smuzhiyun 		do_printenv = 0;
236*4882a593Smuzhiyun 	} else {
237*4882a593Smuzhiyun 		fprintf(stderr,
238*4882a593Smuzhiyun 			"Identity crisis - may be called as `%s' or as `%s' but not as `%s'\n",
239*4882a593Smuzhiyun 			CMD_PRINTENV, CMD_SETENV, _cmdname);
240*4882a593Smuzhiyun 		exit(EXIT_FAILURE);
241*4882a593Smuzhiyun 	}
242*4882a593Smuzhiyun 
243*4882a593Smuzhiyun 	if (do_printenv) {
244*4882a593Smuzhiyun 		if (parse_printenv_args(argc, argv))
245*4882a593Smuzhiyun 			exit(EXIT_FAILURE);
246*4882a593Smuzhiyun 	} else {
247*4882a593Smuzhiyun 		if (parse_setenv_args(argc, argv))
248*4882a593Smuzhiyun 			exit(EXIT_FAILURE);
249*4882a593Smuzhiyun 	}
250*4882a593Smuzhiyun 
251*4882a593Smuzhiyun 	/* shift parsed flags, jump to non-option arguments */
252*4882a593Smuzhiyun 	argc -= optind;
253*4882a593Smuzhiyun 	argv += optind;
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun 	if (env_opts.lockname) {
256*4882a593Smuzhiyun 		lockname = malloc(sizeof(env_opts.lockname) +
257*4882a593Smuzhiyun 				sizeof(CMD_PRINTENV) + 10);
258*4882a593Smuzhiyun 		if (!lockname) {
259*4882a593Smuzhiyun 			fprintf(stderr, "Unable allocate memory");
260*4882a593Smuzhiyun 			exit(EXIT_FAILURE);
261*4882a593Smuzhiyun 		}
262*4882a593Smuzhiyun 
263*4882a593Smuzhiyun 		sprintf(lockname, "%s/%s.lock",
264*4882a593Smuzhiyun 			env_opts.lockname, CMD_PRINTENV);
265*4882a593Smuzhiyun 	}
266*4882a593Smuzhiyun 
267*4882a593Smuzhiyun 	lockfd = open(lockname, O_WRONLY | O_CREAT | O_TRUNC, 0666);
268*4882a593Smuzhiyun 	if (-1 == lockfd) {
269*4882a593Smuzhiyun 		fprintf(stderr, "Error opening lock file %s\n", lockname);
270*4882a593Smuzhiyun 		return EXIT_FAILURE;
271*4882a593Smuzhiyun 	}
272*4882a593Smuzhiyun 
273*4882a593Smuzhiyun 	if (-1 == flock(lockfd, LOCK_EX)) {
274*4882a593Smuzhiyun 		fprintf(stderr, "Error locking file %s\n", lockname);
275*4882a593Smuzhiyun 		close(lockfd);
276*4882a593Smuzhiyun 		return EXIT_FAILURE;
277*4882a593Smuzhiyun 	}
278*4882a593Smuzhiyun 
279*4882a593Smuzhiyun 	if (do_printenv) {
280*4882a593Smuzhiyun 		if (fw_printenv(argc, argv, noheader, &env_opts) != 0)
281*4882a593Smuzhiyun 			retval = EXIT_FAILURE;
282*4882a593Smuzhiyun 	} else {
283*4882a593Smuzhiyun 		if (!script_file) {
284*4882a593Smuzhiyun 			if (fw_env_set(argc, argv, &env_opts) != 0)
285*4882a593Smuzhiyun 				retval = EXIT_FAILURE;
286*4882a593Smuzhiyun 		} else {
287*4882a593Smuzhiyun 			if (fw_parse_script(script_file, &env_opts) != 0)
288*4882a593Smuzhiyun 				retval = EXIT_FAILURE;
289*4882a593Smuzhiyun 		}
290*4882a593Smuzhiyun 	}
291*4882a593Smuzhiyun 
292*4882a593Smuzhiyun 	if (env_opts.lockname)
293*4882a593Smuzhiyun 		free(lockname);
294*4882a593Smuzhiyun 
295*4882a593Smuzhiyun 	flock(lockfd, LOCK_UN);
296*4882a593Smuzhiyun 	close(lockfd);
297*4882a593Smuzhiyun 	return retval;
298*4882a593Smuzhiyun }
299