blob: daf468823f7cf8952ea97df9158f33c6ded448a9 [file] [log] [blame]
wdenk6aff3112002-12-17 01:51:00 +00001/*
Grant Ericksonbc117562008-05-06 20:16:15 -07002 * (C) Copyright 2000-2008
wdenk6aff3112002-12-17 01:51:00 +00003 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4 *
Wolfgang Denk3765b3e2013-10-07 13:07:26 +02005 * SPDX-License-Identifier: GPL-2.0+
wdenk6aff3112002-12-17 01:51:00 +00006 */
7
8/*
wdenk3bac3512003-03-12 10:41:04 +00009 * Command line user interface to firmware (=U-Boot) environment.
wdenk6aff3112002-12-17 01:51:00 +000010 *
11 * Implements:
Marek Vasuta8a752c2014-03-05 19:59:52 +010012 * fw_printenv [ -a key ] [[ -n name ] | [ name ... ]]
Grant Ericksonbc117562008-05-06 20:16:15 -070013 * - prints the value of a single environment variable
14 * "name", the ``name=value'' pairs of one or more
15 * environment variables "name", or the whole
16 * environment if no names are specified.
Marek Vasuta8a752c2014-03-05 19:59:52 +010017 * fw_setenv [ -a key ] name [ value ... ]
wdenk6aff3112002-12-17 01:51:00 +000018 * - If a name without any values is given, the variable
19 * with this name is deleted from the environment;
20 * otherwise, all "value" arguments are concatenated,
Grant Ericksonbc117562008-05-06 20:16:15 -070021 * separated by single blank characters, and the
wdenk6aff3112002-12-17 01:51:00 +000022 * resulting string is assigned to the environment
23 * variable "name"
Marek Vasuta8a752c2014-03-05 19:59:52 +010024 *
25 * If '-a key' is specified, the env block is encrypted with AES 128 CBC.
26 * The 'key' argument is in the format of 32 hexadecimal numbers (16 bytes
27 * of AES key), eg. '-a aabbccddeeff00112233445566778899'.
wdenk6aff3112002-12-17 01:51:00 +000028 */
29
Joe Hershbergere4a223f2012-10-03 09:38:49 +000030#include <fcntl.h>
31#include <getopt.h>
wdenk6aff3112002-12-17 01:51:00 +000032#include <stdio.h>
33#include <string.h>
34#include <stdlib.h>
Joe Hershbergere4a223f2012-10-03 09:38:49 +000035#include <sys/file.h>
36#include <unistd.h>
wdenk6aff3112002-12-17 01:51:00 +000037#include "fw_env.h"
38
39#define CMD_PRINTENV "fw_printenv"
40#define CMD_SETENV "fw_setenv"
41
Stefano Babicbd7b26f2010-05-24 12:08:16 +020042static struct option long_options[] = {
43 {"script", required_argument, NULL, 's'},
44 {"help", no_argument, NULL, 'h'},
45 {NULL, 0, NULL, 0}
46};
47
Andreas Fenkart371ee132015-12-09 13:13:24 +010048struct common_args common_args;
Andreas Fenkart07ce9442015-12-09 13:13:23 +010049struct printenv_args printenv_args;
50struct setenv_args setenv_args;
51
Stefano Babicbd7b26f2010-05-24 12:08:16 +020052void usage(void)
53{
54
55 fprintf(stderr, "fw_printenv/fw_setenv, "
56 "a command line interface to U-Boot environment\n\n"
Michael Heimpold9884f442015-10-27 22:34:49 +010057#ifndef CONFIG_FILE
Marek Vasuta8a752c2014-03-05 19:59:52 +010058 "usage:\tfw_printenv [-a key] [-n] [variable name]\n"
59 "\tfw_setenv [-a key] [variable name] [variable value]\n"
Michael Heimpold9884f442015-10-27 22:34:49 +010060#else
61 "usage:\tfw_printenv [-c /my/fw_env.config] [-a key] [-n] [variable name]\n"
62 "\tfw_setenv [-c /my/fw_env.config] [-a key] [variable name] [variable value]\n"
63#endif
Stefano Babicbd7b26f2010-05-24 12:08:16 +020064 "\tfw_setenv -s [ file ]\n"
65 "\tfw_setenv -s - < [ file ]\n\n"
66 "The file passed as argument contains only pairs "
67 "name / value\n"
68 "Example:\n"
69 "# Any line starting with # is treated as comment\n"
70 "\n"
71 "\t netdev eth0\n"
72 "\t kernel_addr 400000\n"
73 "\t var1\n"
74 "\t var2 The quick brown fox jumps over the "
75 "lazy dog\n"
76 "\n"
77 "A variable without value will be dropped. It is possible\n"
78 "to put any number of spaces between the fields, but any\n"
79 "space inside the value is treated as part of the value "
80 "itself.\n\n"
81 );
82}
83
Andreas Fenkart07ce9442015-12-09 13:13:23 +010084int parse_printenv_args(int argc, char *argv[])
wdenk6aff3112002-12-17 01:51:00 +000085{
Stefano Babicbd7b26f2010-05-24 12:08:16 +020086 int c;
wdenk6aff3112002-12-17 01:51:00 +000087
Andreas Fenkart371ee132015-12-09 13:13:24 +010088#ifdef CONFIG_FILE
89 common_args.config_file = CONFIG_FILE;
90#endif
91
Michael Heimpold9884f442015-10-27 22:34:49 +010092 while ((c = getopt_long (argc, argv, "a:c:ns:h",
Stefano Babicbd7b26f2010-05-24 12:08:16 +020093 long_options, NULL)) != EOF) {
94 switch (c) {
Marek Vasuta8a752c2014-03-05 19:59:52 +010095 case 'a':
Andreas Fenkart371ee132015-12-09 13:13:24 +010096 if (parse_aes_key(optarg, common_args.aes_key)) {
97 fprintf(stderr, "AES key parse error\n");
98 return EXIT_FAILURE;
99 }
100 common_args.aes_flag = 1;
Marek Vasuta8a752c2014-03-05 19:59:52 +0100101 break;
Andreas Fenkart371ee132015-12-09 13:13:24 +0100102#ifdef CONFIG_FILE
Michael Heimpold9884f442015-10-27 22:34:49 +0100103 case 'c':
Andreas Fenkart371ee132015-12-09 13:13:24 +0100104 common_args.config_file = optarg;
Michael Heimpold9884f442015-10-27 22:34:49 +0100105 break;
Andreas Fenkart371ee132015-12-09 13:13:24 +0100106#endif
Daniel Hobi122bc082010-09-15 19:46:26 +0200107 case 'n':
Andreas Fenkart371ee132015-12-09 13:13:24 +0100108 printenv_args.name_suppress = 1;
Daniel Hobi122bc082010-09-15 19:46:26 +0200109 break;
Andreas Fenkart07ce9442015-12-09 13:13:23 +0100110 case 'h':
111 usage();
112 exit(EXIT_SUCCESS);
113 break;
114 default: /* '?' */
115 usage();
116 exit(EXIT_FAILURE);
117 break;
118 }
119 }
120 return 0;
121}
122
123int parse_setenv_args(int argc, char *argv[])
124{
125 int c;
126
Andreas Fenkart371ee132015-12-09 13:13:24 +0100127#ifdef CONFIG_FILE
128 common_args.config_file = CONFIG_FILE;
129#endif
130
Andreas Fenkart07ce9442015-12-09 13:13:23 +0100131 while ((c = getopt_long (argc, argv, "a:c:ns:h",
132 long_options, NULL)) != EOF) {
133 switch (c) {
134 case 'a':
Andreas Fenkart371ee132015-12-09 13:13:24 +0100135 if (parse_aes_key(optarg, common_args.aes_key)) {
136 fprintf(stderr, "AES key parse error\n");
137 return EXIT_FAILURE;
138 }
139 common_args.aes_flag = 1;
Andreas Fenkart07ce9442015-12-09 13:13:23 +0100140 break;
Andreas Fenkart371ee132015-12-09 13:13:24 +0100141#ifdef CONFIG_FILE
Andreas Fenkart07ce9442015-12-09 13:13:23 +0100142 case 'c':
Andreas Fenkart371ee132015-12-09 13:13:24 +0100143 common_args.config_file = optarg;
Andreas Fenkart07ce9442015-12-09 13:13:23 +0100144 break;
Andreas Fenkart371ee132015-12-09 13:13:24 +0100145#endif
Stefano Babicbd7b26f2010-05-24 12:08:16 +0200146 case 's':
Andreas Fenkart07ce9442015-12-09 13:13:23 +0100147 setenv_args.script_file = optarg;
Stefano Babicbd7b26f2010-05-24 12:08:16 +0200148 break;
149 case 'h':
150 usage();
Andreas Fenkart07ce9442015-12-09 13:13:23 +0100151 exit(EXIT_SUCCESS);
152 break;
Daniel Hobi29ccd7c2010-09-16 14:36:09 +0200153 default: /* '?' */
Andreas Fenkart07ce9442015-12-09 13:13:23 +0100154 usage();
155 exit(EXIT_FAILURE);
156 break;
Stefano Babicbd7b26f2010-05-24 12:08:16 +0200157 }
158 }
Andreas Fenkart07ce9442015-12-09 13:13:23 +0100159 return 0;
160}
161
162int main(int argc, char *argv[])
163{
164 char *cmdname = *argv;
165 const char *lockname = "/var/lock/" CMD_PRINTENV ".lock";
166 int lockfd = -1;
167 int retval = EXIT_SUCCESS;
168
169 if (strrchr(cmdname, '/') != NULL)
170 cmdname = strrchr(cmdname, '/') + 1;
171
172 if (strcmp(cmdname, CMD_PRINTENV) == 0) {
173 if (parse_printenv_args(argc, argv))
174 exit(EXIT_FAILURE);
175 } else if (strcmp(cmdname, CMD_SETENV) == 0) {
176 if (parse_setenv_args(argc, argv))
177 exit(EXIT_FAILURE);
178 } else {
179 fprintf(stderr,
180 "Identity crisis - may be called as `%s' or as `%s' but not as `%s'\n",
181 CMD_PRINTENV, CMD_SETENV, cmdname);
182 exit(EXIT_FAILURE);
183 }
184
Andreas Fenkart1ce68692015-12-09 13:13:25 +0100185 /* shift parsed flags, jump to non-option arguments */
186 argc -= optind;
187 argv += optind;
188
Andreas Fenkart07ce9442015-12-09 13:13:23 +0100189 lockfd = open(lockname, O_WRONLY | O_CREAT | O_TRUNC, 0666);
190 if (-1 == lockfd) {
191 fprintf(stderr, "Error opening lock file %s\n", lockname);
192 return EXIT_FAILURE;
193 }
194
195 if (-1 == flock(lockfd, LOCK_EX)) {
196 fprintf(stderr, "Error locking file %s\n", lockname);
197 close(lockfd);
198 return EXIT_FAILURE;
199 }
Stefano Babicbd7b26f2010-05-24 12:08:16 +0200200
wdenk6aff3112002-12-17 01:51:00 +0000201 if (strcmp(cmdname, CMD_PRINTENV) == 0) {
Joe Hershbergere4a223f2012-10-03 09:38:49 +0000202 if (fw_printenv(argc, argv) != 0)
203 retval = EXIT_FAILURE;
wdenk6aff3112002-12-17 01:51:00 +0000204 } else if (strcmp(cmdname, CMD_SETENV) == 0) {
Andreas Fenkart07ce9442015-12-09 13:13:23 +0100205 if (!setenv_args.script_file) {
Stefano Babicbd7b26f2010-05-24 12:08:16 +0200206 if (fw_setenv(argc, argv) != 0)
Joe Hershbergere4a223f2012-10-03 09:38:49 +0000207 retval = EXIT_FAILURE;
Stefano Babicbd7b26f2010-05-24 12:08:16 +0200208 } else {
Andreas Fenkart07ce9442015-12-09 13:13:23 +0100209 if (fw_parse_script(setenv_args.script_file) != 0)
Joe Hershbergere4a223f2012-10-03 09:38:49 +0000210 retval = EXIT_FAILURE;
Stefano Babicbd7b26f2010-05-24 12:08:16 +0200211 }
wdenk6aff3112002-12-17 01:51:00 +0000212 }
213
Joe Hershbergere4a223f2012-10-03 09:38:49 +0000214 flock(lockfd, LOCK_UN);
215 close(lockfd);
216 return retval;
wdenk6aff3112002-12-17 01:51:00 +0000217}