xref: /rk3399_rockchip-uboot/tools/env/fw_env_main.c (revision 1ce686978c03d4fd025c7e93b7a18d4a87f547ec)
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 
8407ce9440SAndreas Fenkart int parse_printenv_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 
929884f44cSMichael Heimpold 	while ((c = getopt_long (argc, argv, "a:c:ns:h",
93bd7b26f8SStefano Babic 		long_options, NULL)) != 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");
98371ee137SAndreas Fenkart 				return 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
107122bc088SDaniel Hobi 		case 'n':
108371ee137SAndreas Fenkart 			printenv_args.name_suppress = 1;
109122bc088SDaniel Hobi 			break;
11007ce9440SAndreas Fenkart 		case 'h':
11107ce9440SAndreas Fenkart 			usage();
11207ce9440SAndreas Fenkart 			exit(EXIT_SUCCESS);
11307ce9440SAndreas Fenkart 			break;
11407ce9440SAndreas Fenkart 		default: /* '?' */
11507ce9440SAndreas Fenkart 			usage();
11607ce9440SAndreas Fenkart 			exit(EXIT_FAILURE);
11707ce9440SAndreas Fenkart 			break;
11807ce9440SAndreas Fenkart 		}
11907ce9440SAndreas Fenkart 	}
12007ce9440SAndreas Fenkart 	return 0;
12107ce9440SAndreas Fenkart }
12207ce9440SAndreas Fenkart 
12307ce9440SAndreas Fenkart int parse_setenv_args(int argc, char *argv[])
12407ce9440SAndreas Fenkart {
12507ce9440SAndreas Fenkart 	int c;
12607ce9440SAndreas Fenkart 
127371ee137SAndreas Fenkart #ifdef CONFIG_FILE
128371ee137SAndreas Fenkart 	common_args.config_file = CONFIG_FILE;
129371ee137SAndreas Fenkart #endif
130371ee137SAndreas Fenkart 
13107ce9440SAndreas Fenkart 	while ((c = getopt_long (argc, argv, "a:c:ns:h",
13207ce9440SAndreas Fenkart 		long_options, NULL)) != EOF) {
13307ce9440SAndreas Fenkart 		switch (c) {
13407ce9440SAndreas Fenkart 		case 'a':
135371ee137SAndreas Fenkart 			if (parse_aes_key(optarg, common_args.aes_key)) {
136371ee137SAndreas Fenkart 				fprintf(stderr, "AES key parse error\n");
137371ee137SAndreas Fenkart 				return EXIT_FAILURE;
138371ee137SAndreas Fenkart 			}
139371ee137SAndreas Fenkart 			common_args.aes_flag = 1;
14007ce9440SAndreas Fenkart 			break;
141371ee137SAndreas Fenkart #ifdef CONFIG_FILE
14207ce9440SAndreas Fenkart 		case 'c':
143371ee137SAndreas Fenkart 			common_args.config_file = optarg;
14407ce9440SAndreas Fenkart 			break;
145371ee137SAndreas Fenkart #endif
146bd7b26f8SStefano Babic 		case 's':
14707ce9440SAndreas Fenkart 			setenv_args.script_file = optarg;
148bd7b26f8SStefano Babic 			break;
149bd7b26f8SStefano Babic 		case 'h':
150bd7b26f8SStefano Babic 			usage();
15107ce9440SAndreas Fenkart 			exit(EXIT_SUCCESS);
15207ce9440SAndreas Fenkart 			break;
15329ccd7c3SDaniel Hobi 		default: /* '?' */
15407ce9440SAndreas Fenkart 			usage();
15507ce9440SAndreas Fenkart 			exit(EXIT_FAILURE);
15607ce9440SAndreas Fenkart 			break;
157bd7b26f8SStefano Babic 		}
158bd7b26f8SStefano Babic 	}
15907ce9440SAndreas Fenkart 	return 0;
16007ce9440SAndreas Fenkart }
16107ce9440SAndreas Fenkart 
16207ce9440SAndreas Fenkart int main(int argc, char *argv[])
16307ce9440SAndreas Fenkart {
16407ce9440SAndreas Fenkart 	char *cmdname = *argv;
16507ce9440SAndreas Fenkart 	const char *lockname = "/var/lock/" CMD_PRINTENV ".lock";
16607ce9440SAndreas Fenkart 	int lockfd = -1;
16707ce9440SAndreas Fenkart 	int retval = EXIT_SUCCESS;
16807ce9440SAndreas Fenkart 
16907ce9440SAndreas Fenkart 	if (strrchr(cmdname, '/') != NULL)
17007ce9440SAndreas Fenkart 		cmdname = strrchr(cmdname, '/') + 1;
17107ce9440SAndreas Fenkart 
17207ce9440SAndreas Fenkart 	if (strcmp(cmdname, CMD_PRINTENV) == 0) {
17307ce9440SAndreas Fenkart 		if (parse_printenv_args(argc, argv))
17407ce9440SAndreas Fenkart 			exit(EXIT_FAILURE);
17507ce9440SAndreas Fenkart 	} else if (strcmp(cmdname, CMD_SETENV) == 0) {
17607ce9440SAndreas Fenkart 		if (parse_setenv_args(argc, argv))
17707ce9440SAndreas Fenkart 			exit(EXIT_FAILURE);
17807ce9440SAndreas Fenkart 	} else {
17907ce9440SAndreas Fenkart 		fprintf(stderr,
18007ce9440SAndreas Fenkart 			"Identity crisis - may be called as `%s' or as `%s' but not as `%s'\n",
18107ce9440SAndreas Fenkart 			CMD_PRINTENV, CMD_SETENV, cmdname);
18207ce9440SAndreas Fenkart 		exit(EXIT_FAILURE);
18307ce9440SAndreas Fenkart 	}
18407ce9440SAndreas Fenkart 
185*1ce68697SAndreas Fenkart 	/* shift parsed flags, jump to non-option arguments */
186*1ce68697SAndreas Fenkart 	argc -= optind;
187*1ce68697SAndreas Fenkart 	argv += optind;
188*1ce68697SAndreas Fenkart 
18907ce9440SAndreas Fenkart 	lockfd = open(lockname, O_WRONLY | O_CREAT | O_TRUNC, 0666);
19007ce9440SAndreas Fenkart 	if (-1 == lockfd) {
19107ce9440SAndreas Fenkart 		fprintf(stderr, "Error opening lock file %s\n", lockname);
19207ce9440SAndreas Fenkart 		return EXIT_FAILURE;
19307ce9440SAndreas Fenkart 	}
19407ce9440SAndreas Fenkart 
19507ce9440SAndreas Fenkart 	if (-1 == flock(lockfd, LOCK_EX)) {
19607ce9440SAndreas Fenkart 		fprintf(stderr, "Error locking file %s\n", lockname);
19707ce9440SAndreas Fenkart 		close(lockfd);
19807ce9440SAndreas Fenkart 		return EXIT_FAILURE;
19907ce9440SAndreas Fenkart 	}
200bd7b26f8SStefano Babic 
2016aff3115Swdenk 	if (strcmp(cmdname, CMD_PRINTENV) == 0) {
202bc11756dSGrant Erickson 		if (fw_printenv(argc, argv) != 0)
203e4a223f0SJoe Hershberger 			retval = EXIT_FAILURE;
2046aff3115Swdenk 	} else if (strcmp(cmdname, CMD_SETENV) == 0) {
20507ce9440SAndreas Fenkart 		if (!setenv_args.script_file) {
2066aff3115Swdenk 			if (fw_setenv(argc, argv) != 0)
207e4a223f0SJoe Hershberger 				retval = EXIT_FAILURE;
208bd7b26f8SStefano Babic 		} else {
20907ce9440SAndreas Fenkart 			if (fw_parse_script(setenv_args.script_file) != 0)
210e4a223f0SJoe Hershberger 				retval = EXIT_FAILURE;
211bd7b26f8SStefano Babic 		}
212e4a223f0SJoe Hershberger 	}
213e4a223f0SJoe Hershberger 
214e4a223f0SJoe Hershberger 	flock(lockfd, LOCK_UN);
215e4a223f0SJoe Hershberger 	close(lockfd);
216e4a223f0SJoe Hershberger 	return retval;
2176aff3115Swdenk }
218