xref: /rk3399_rockchip-uboot/tools/env/fw_env_main.c (revision af93e3d8ababbca05f94ed3ad89e3e277b31ffd5)
16aff3115Swdenk /*
2bc11756dSGrant Erickson  * (C) Copyright 2000-2008
36aff3115Swdenk  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
46aff3115Swdenk  *
51a459660SWolfgang Denk  * SPDX-License-Identifier:	GPL-2.0+
66aff3115Swdenk  */
76aff3115Swdenk 
86aff3115Swdenk /*
93bac3513Swdenk  * Command line user interface to firmware (=U-Boot) environment.
106aff3115Swdenk  *
116aff3115Swdenk  * Implements:
12a8a752c0SMarek Vasut  *	fw_printenv [ -a key ] [[ -n name ] | [ name ... ]]
13bc11756dSGrant Erickson  *              - prints the value of a single environment variable
14bc11756dSGrant Erickson  *                "name", the ``name=value'' pairs of one or more
15bc11756dSGrant Erickson  *                environment variables "name", or the whole
16bc11756dSGrant Erickson  *                environment if no names are specified.
17a8a752c0SMarek Vasut  *	fw_setenv [ -a key ] name [ value ... ]
186aff3115Swdenk  *		- If a name without any values is given, the variable
196aff3115Swdenk  *		  with this name is deleted from the environment;
206aff3115Swdenk  *		  otherwise, all "value" arguments are concatenated,
21bc11756dSGrant Erickson  *		  separated by single blank characters, and the
226aff3115Swdenk  *		  resulting string is assigned to the environment
236aff3115Swdenk  *		  variable "name"
24a8a752c0SMarek Vasut  *
25a8a752c0SMarek Vasut  * If '-a key' is specified, the env block is encrypted with AES 128 CBC.
26a8a752c0SMarek Vasut  * The 'key' argument is in the format of 32 hexadecimal numbers (16 bytes
27a8a752c0SMarek Vasut  * of AES key), eg. '-a aabbccddeeff00112233445566778899'.
286aff3115Swdenk  */
296aff3115Swdenk 
30e4a223f0SJoe Hershberger #include <fcntl.h>
31e4a223f0SJoe Hershberger #include <getopt.h>
326aff3115Swdenk #include <stdio.h>
336aff3115Swdenk #include <string.h>
346aff3115Swdenk #include <stdlib.h>
35e4a223f0SJoe Hershberger #include <sys/file.h>
36e4a223f0SJoe Hershberger #include <unistd.h>
376aff3115Swdenk #include "fw_env.h"
386aff3115Swdenk 
396aff3115Swdenk #define	CMD_PRINTENV	"fw_printenv"
406aff3115Swdenk #define CMD_SETENV	"fw_setenv"
416aff3115Swdenk 
42bd7b26f8SStefano Babic static struct option long_options[] = {
43bd7b26f8SStefano Babic 	{"script", required_argument, NULL, 's'},
44bd7b26f8SStefano Babic 	{"help", no_argument, NULL, 'h'},
45bd7b26f8SStefano Babic 	{NULL, 0, NULL, 0}
46bd7b26f8SStefano Babic };
47bd7b26f8SStefano Babic 
48371ee137SAndreas Fenkart struct common_args common_args;
4907ce9440SAndreas Fenkart struct printenv_args printenv_args;
5007ce9440SAndreas Fenkart struct setenv_args setenv_args;
5107ce9440SAndreas Fenkart 
52bd7b26f8SStefano Babic void usage(void)
53bd7b26f8SStefano Babic {
54bd7b26f8SStefano Babic 
55bd7b26f8SStefano Babic 	fprintf(stderr, "fw_printenv/fw_setenv, "
56bd7b26f8SStefano Babic 		"a command line interface to U-Boot environment\n\n"
579884f44cSMichael Heimpold #ifndef CONFIG_FILE
58a8a752c0SMarek Vasut 		"usage:\tfw_printenv [-a key] [-n] [variable name]\n"
59a8a752c0SMarek Vasut 		"\tfw_setenv [-a key] [variable name] [variable value]\n"
609884f44cSMichael Heimpold #else
619884f44cSMichael Heimpold 		"usage:\tfw_printenv [-c /my/fw_env.config] [-a key] [-n] [variable name]\n"
629884f44cSMichael Heimpold 		"\tfw_setenv [-c /my/fw_env.config] [-a key] [variable name] [variable value]\n"
639884f44cSMichael Heimpold #endif
64bd7b26f8SStefano Babic 		"\tfw_setenv -s [ file ]\n"
65bd7b26f8SStefano Babic 		"\tfw_setenv -s - < [ file ]\n\n"
66bd7b26f8SStefano Babic 		"The file passed as argument contains only pairs "
67bd7b26f8SStefano Babic 		"name / value\n"
68bd7b26f8SStefano Babic 		"Example:\n"
69bd7b26f8SStefano Babic 		"# Any line starting with # is treated as comment\n"
70bd7b26f8SStefano Babic 		"\n"
71bd7b26f8SStefano Babic 		"\t      netdev         eth0\n"
72bd7b26f8SStefano Babic 		"\t      kernel_addr    400000\n"
73bd7b26f8SStefano Babic 		"\t      var1\n"
74bd7b26f8SStefano Babic 		"\t      var2          The quick brown fox jumps over the "
75bd7b26f8SStefano Babic 		"lazy dog\n"
76bd7b26f8SStefano Babic 		"\n"
77bd7b26f8SStefano Babic 		"A variable without value will be dropped. It is possible\n"
78bd7b26f8SStefano Babic 		"to put any number of spaces between the fields, but any\n"
79bd7b26f8SStefano Babic 		"space inside the value is treated as part of the value "
80bd7b26f8SStefano Babic 		"itself.\n\n"
81bd7b26f8SStefano Babic 	);
82bd7b26f8SStefano Babic }
83bd7b26f8SStefano Babic 
84*af93e3d8SAndreas Fenkart static void parse_common_args(int argc, char *argv[])
856aff3115Swdenk {
86bd7b26f8SStefano Babic 	int c;
876aff3115Swdenk 
88371ee137SAndreas Fenkart #ifdef CONFIG_FILE
89371ee137SAndreas Fenkart 	common_args.config_file = CONFIG_FILE;
90371ee137SAndreas Fenkart #endif
91371ee137SAndreas Fenkart 
92*af93e3d8SAndreas Fenkart 	while ((c = getopt_long(argc, argv, ":a:c:h", long_options, NULL)) !=
93*af93e3d8SAndreas Fenkart 	       EOF) {
94bd7b26f8SStefano Babic 		switch (c) {
95a8a752c0SMarek Vasut 		case 'a':
96371ee137SAndreas Fenkart 			if (parse_aes_key(optarg, common_args.aes_key)) {
97371ee137SAndreas Fenkart 				fprintf(stderr, "AES key parse error\n");
98*af93e3d8SAndreas Fenkart 				exit(EXIT_FAILURE);
99371ee137SAndreas Fenkart 			}
100371ee137SAndreas Fenkart 			common_args.aes_flag = 1;
101a8a752c0SMarek Vasut 			break;
102371ee137SAndreas Fenkart #ifdef CONFIG_FILE
1039884f44cSMichael Heimpold 		case 'c':
104371ee137SAndreas Fenkart 			common_args.config_file = optarg;
1059884f44cSMichael Heimpold 			break;
106371ee137SAndreas Fenkart #endif
10707ce9440SAndreas Fenkart 		case 'h':
10807ce9440SAndreas Fenkart 			usage();
10907ce9440SAndreas Fenkart 			exit(EXIT_SUCCESS);
11007ce9440SAndreas Fenkart 			break;
111*af93e3d8SAndreas Fenkart 		default:
112*af93e3d8SAndreas Fenkart 			/* ignore unknown options */
113*af93e3d8SAndreas Fenkart 			break;
114*af93e3d8SAndreas Fenkart 		}
115*af93e3d8SAndreas Fenkart 	}
116*af93e3d8SAndreas Fenkart 
117*af93e3d8SAndreas Fenkart 	/* Reset getopt for the next pass. */
118*af93e3d8SAndreas Fenkart 	opterr = 1;
119*af93e3d8SAndreas Fenkart 	optind = 1;
120*af93e3d8SAndreas Fenkart }
121*af93e3d8SAndreas Fenkart 
122*af93e3d8SAndreas Fenkart int parse_printenv_args(int argc, char *argv[])
123*af93e3d8SAndreas Fenkart {
124*af93e3d8SAndreas Fenkart 	int c;
125*af93e3d8SAndreas Fenkart 
126*af93e3d8SAndreas Fenkart 	parse_common_args(argc, argv);
127*af93e3d8SAndreas Fenkart 
128*af93e3d8SAndreas Fenkart 	while ((c = getopt_long(argc, argv, "a:c:ns:h", long_options, NULL)) !=
129*af93e3d8SAndreas Fenkart 	       EOF) {
130*af93e3d8SAndreas Fenkart 		switch (c) {
131*af93e3d8SAndreas Fenkart 		case 'n':
132*af93e3d8SAndreas Fenkart 			printenv_args.name_suppress = 1;
133*af93e3d8SAndreas Fenkart 			break;
134*af93e3d8SAndreas Fenkart 		case 'a':
135*af93e3d8SAndreas Fenkart 		case 'c':
136*af93e3d8SAndreas Fenkart 		case 'h':
137*af93e3d8SAndreas Fenkart 			/* ignore common options */
138*af93e3d8SAndreas Fenkart 			break;
13907ce9440SAndreas Fenkart 		default: /* '?' */
14007ce9440SAndreas Fenkart 			usage();
14107ce9440SAndreas Fenkart 			exit(EXIT_FAILURE);
14207ce9440SAndreas Fenkart 			break;
14307ce9440SAndreas Fenkart 		}
14407ce9440SAndreas Fenkart 	}
14507ce9440SAndreas Fenkart 	return 0;
14607ce9440SAndreas Fenkart }
14707ce9440SAndreas Fenkart 
14807ce9440SAndreas Fenkart int parse_setenv_args(int argc, char *argv[])
14907ce9440SAndreas Fenkart {
15007ce9440SAndreas Fenkart 	int c;
15107ce9440SAndreas Fenkart 
152*af93e3d8SAndreas Fenkart 	parse_common_args(argc, argv);
153371ee137SAndreas Fenkart 
154*af93e3d8SAndreas Fenkart 	while ((c = getopt_long(argc, argv, "a:c:ns:h", long_options, NULL)) !=
155*af93e3d8SAndreas Fenkart 	       EOF) {
15607ce9440SAndreas Fenkart 		switch (c) {
157bd7b26f8SStefano Babic 		case 's':
15807ce9440SAndreas Fenkart 			setenv_args.script_file = optarg;
159bd7b26f8SStefano Babic 			break;
160*af93e3d8SAndreas Fenkart 		case 'a':
161*af93e3d8SAndreas Fenkart 		case 'c':
162bd7b26f8SStefano Babic 		case 'h':
163*af93e3d8SAndreas Fenkart 			/* ignore common options */
16407ce9440SAndreas Fenkart 			break;
16529ccd7c3SDaniel Hobi 		default: /* '?' */
16607ce9440SAndreas Fenkart 			usage();
16707ce9440SAndreas Fenkart 			exit(EXIT_FAILURE);
16807ce9440SAndreas Fenkart 			break;
169bd7b26f8SStefano Babic 		}
170bd7b26f8SStefano Babic 	}
17107ce9440SAndreas Fenkart 	return 0;
17207ce9440SAndreas Fenkart }
17307ce9440SAndreas Fenkart 
17407ce9440SAndreas Fenkart int main(int argc, char *argv[])
17507ce9440SAndreas Fenkart {
17607ce9440SAndreas Fenkart 	char *cmdname = *argv;
17707ce9440SAndreas Fenkart 	const char *lockname = "/var/lock/" CMD_PRINTENV ".lock";
17807ce9440SAndreas Fenkart 	int lockfd = -1;
17907ce9440SAndreas Fenkart 	int retval = EXIT_SUCCESS;
18007ce9440SAndreas Fenkart 
18107ce9440SAndreas Fenkart 	if (strrchr(cmdname, '/') != NULL)
18207ce9440SAndreas Fenkart 		cmdname = strrchr(cmdname, '/') + 1;
18307ce9440SAndreas Fenkart 
18407ce9440SAndreas Fenkart 	if (strcmp(cmdname, CMD_PRINTENV) == 0) {
18507ce9440SAndreas Fenkart 		if (parse_printenv_args(argc, argv))
18607ce9440SAndreas Fenkart 			exit(EXIT_FAILURE);
18707ce9440SAndreas Fenkart 	} else if (strcmp(cmdname, CMD_SETENV) == 0) {
18807ce9440SAndreas Fenkart 		if (parse_setenv_args(argc, argv))
18907ce9440SAndreas Fenkart 			exit(EXIT_FAILURE);
19007ce9440SAndreas Fenkart 	} else {
19107ce9440SAndreas Fenkart 		fprintf(stderr,
19207ce9440SAndreas Fenkart 			"Identity crisis - may be called as `%s' or as `%s' but not as `%s'\n",
19307ce9440SAndreas Fenkart 			CMD_PRINTENV, CMD_SETENV, cmdname);
19407ce9440SAndreas Fenkart 		exit(EXIT_FAILURE);
19507ce9440SAndreas Fenkart 	}
19607ce9440SAndreas Fenkart 
1971ce68697SAndreas Fenkart 	/* shift parsed flags, jump to non-option arguments */
1981ce68697SAndreas Fenkart 	argc -= optind;
1991ce68697SAndreas Fenkart 	argv += optind;
2001ce68697SAndreas Fenkart 
20107ce9440SAndreas Fenkart 	lockfd = open(lockname, O_WRONLY | O_CREAT | O_TRUNC, 0666);
20207ce9440SAndreas Fenkart 	if (-1 == lockfd) {
20307ce9440SAndreas Fenkart 		fprintf(stderr, "Error opening lock file %s\n", lockname);
20407ce9440SAndreas Fenkart 		return EXIT_FAILURE;
20507ce9440SAndreas Fenkart 	}
20607ce9440SAndreas Fenkart 
20707ce9440SAndreas Fenkart 	if (-1 == flock(lockfd, LOCK_EX)) {
20807ce9440SAndreas Fenkart 		fprintf(stderr, "Error locking file %s\n", lockname);
20907ce9440SAndreas Fenkart 		close(lockfd);
21007ce9440SAndreas Fenkart 		return EXIT_FAILURE;
21107ce9440SAndreas Fenkart 	}
212bd7b26f8SStefano Babic 
2136aff3115Swdenk 	if (strcmp(cmdname, CMD_PRINTENV) == 0) {
214bc11756dSGrant Erickson 		if (fw_printenv(argc, argv) != 0)
215e4a223f0SJoe Hershberger 			retval = EXIT_FAILURE;
2166aff3115Swdenk 	} else if (strcmp(cmdname, CMD_SETENV) == 0) {
21707ce9440SAndreas Fenkart 		if (!setenv_args.script_file) {
2186aff3115Swdenk 			if (fw_setenv(argc, argv) != 0)
219e4a223f0SJoe Hershberger 				retval = EXIT_FAILURE;
220bd7b26f8SStefano Babic 		} else {
22107ce9440SAndreas Fenkart 			if (fw_parse_script(setenv_args.script_file) != 0)
222e4a223f0SJoe Hershberger 				retval = EXIT_FAILURE;
223bd7b26f8SStefano Babic 		}
224e4a223f0SJoe Hershberger 	}
225e4a223f0SJoe Hershberger 
226e4a223f0SJoe Hershberger 	flock(lockfd, LOCK_UN);
227e4a223f0SJoe Hershberger 	close(lockfd);
228e4a223f0SJoe Hershberger 	return retval;
2296aff3115Swdenk }
230