blob: b68f1bff0cb07f4ec6e68f973cd54094a1557e27 [file] [log] [blame]
wdenk34b613e2002-12-17 01:51:00 +00001/*
Grant Erickson73a4e5e2008-05-06 20:16:15 -07002 * (C) Copyright 2000-2008
wdenk34b613e2002-12-17 01:51:00 +00003 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4 *
Wolfgang Denkbd8ec7e2013-10-07 13:07:26 +02005 * SPDX-License-Identifier: GPL-2.0+
wdenk34b613e2002-12-17 01:51:00 +00006 */
7
8/*
wdenkef5fe752003-03-12 10:41:04 +00009 * Command line user interface to firmware (=U-Boot) environment.
wdenk34b613e2002-12-17 01:51:00 +000010 *
11 * Implements:
Marek Vasut05ed2a52014-03-05 19:59:52 +010012 * fw_printenv [ -a key ] [[ -n name ] | [ name ... ]]
Grant Erickson73a4e5e2008-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 Vasut05ed2a52014-03-05 19:59:52 +010017 * fw_setenv [ -a key ] name [ value ... ]
wdenk34b613e2002-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 Erickson73a4e5e2008-05-06 20:16:15 -070021 * separated by single blank characters, and the
wdenk34b613e2002-12-17 01:51:00 +000022 * resulting string is assigned to the environment
23 * variable "name"
Marek Vasut05ed2a52014-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'.
wdenk34b613e2002-12-17 01:51:00 +000028 */
29
Joe Hershberger3f1f1752012-10-03 09:38:49 +000030#include <fcntl.h>
31#include <getopt.h>
wdenk34b613e2002-12-17 01:51:00 +000032#include <stdio.h>
33#include <string.h>
34#include <stdlib.h>
Joe Hershberger3f1f1752012-10-03 09:38:49 +000035#include <sys/file.h>
36#include <unistd.h>
wdenk34b613e2002-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 Babicada628b2010-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 Fenkartaa01f8d2015-12-09 13:13:24 +010048struct common_args common_args;
Andreas Fenkart33e91772015-12-09 13:13:23 +010049struct printenv_args printenv_args;
50struct setenv_args setenv_args;
51
Stefano Babicada628b2010-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 Heimpold211e17b2015-10-27 22:34:49 +010057#ifndef CONFIG_FILE
Marek Vasut05ed2a52014-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 Heimpold211e17b2015-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 Babicada628b2010-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 Fenkart33e91772015-12-09 13:13:23 +010084int parse_printenv_args(int argc, char *argv[])
wdenk34b613e2002-12-17 01:51:00 +000085{
Stefano Babicada628b2010-05-24 12:08:16 +020086 int c;
wdenk34b613e2002-12-17 01:51:00 +000087
Andreas Fenkartaa01f8d2015-12-09 13:13:24 +010088#ifdef CONFIG_FILE
89 common_args.config_file = CONFIG_FILE;
90#endif
91
Michael Heimpold211e17b2015-10-27 22:34:49 +010092 while ((c = getopt_long (argc, argv, "a:c:ns:h",
Stefano Babicada628b2010-05-24 12:08:16 +020093 long_options, NULL)) != EOF) {
94 switch (c) {
Marek Vasut05ed2a52014-03-05 19:59:52 +010095 case 'a':
Andreas Fenkartaa01f8d2015-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 Vasut05ed2a52014-03-05 19:59:52 +0100101 break;
Andreas Fenkartaa01f8d2015-12-09 13:13:24 +0100102#ifdef CONFIG_FILE
Michael Heimpold211e17b2015-10-27 22:34:49 +0100103 case 'c':
Andreas Fenkartaa01f8d2015-12-09 13:13:24 +0100104 common_args.config_file = optarg;
Michael Heimpold211e17b2015-10-27 22:34:49 +0100105 break;
Andreas Fenkartaa01f8d2015-12-09 13:13:24 +0100106#endif
Daniel Hobi6c554262010-09-15 19:46:26 +0200107 case 'n':
Andreas Fenkartaa01f8d2015-12-09 13:13:24 +0100108 printenv_args.name_suppress = 1;
Daniel Hobi6c554262010-09-15 19:46:26 +0200109 break;
Andreas Fenkart33e91772015-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 Fenkartaa01f8d2015-12-09 13:13:24 +0100127#ifdef CONFIG_FILE
128 common_args.config_file = CONFIG_FILE;
129#endif
130
Andreas Fenkart33e91772015-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 Fenkartaa01f8d2015-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 Fenkart33e91772015-12-09 13:13:23 +0100140 break;
Andreas Fenkartaa01f8d2015-12-09 13:13:24 +0100141#ifdef CONFIG_FILE
Andreas Fenkart33e91772015-12-09 13:13:23 +0100142 case 'c':
Andreas Fenkartaa01f8d2015-12-09 13:13:24 +0100143 common_args.config_file = optarg;
Andreas Fenkart33e91772015-12-09 13:13:23 +0100144 break;
Andreas Fenkartaa01f8d2015-12-09 13:13:24 +0100145#endif
Stefano Babicada628b2010-05-24 12:08:16 +0200146 case 's':
Andreas Fenkart33e91772015-12-09 13:13:23 +0100147 setenv_args.script_file = optarg;
Stefano Babicada628b2010-05-24 12:08:16 +0200148 break;
149 case 'h':
150 usage();
Andreas Fenkart33e91772015-12-09 13:13:23 +0100151 exit(EXIT_SUCCESS);
152 break;
Daniel Hobi6a20a322010-09-16 14:36:09 +0200153 default: /* '?' */
Andreas Fenkart33e91772015-12-09 13:13:23 +0100154 usage();
155 exit(EXIT_FAILURE);
156 break;
Stefano Babicada628b2010-05-24 12:08:16 +0200157 }
158 }
Andreas Fenkart33e91772015-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;
Stefano Babicada628b2010-05-24 12:08:16 +0200171
wdenk34b613e2002-12-17 01:51:00 +0000172 if (strcmp(cmdname, CMD_PRINTENV) == 0) {
Andreas Fenkart33e91772015-12-09 13:13:23 +0100173 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
185 lockfd = open(lockname, O_WRONLY | O_CREAT | O_TRUNC, 0666);
186 if (-1 == lockfd) {
187 fprintf(stderr, "Error opening lock file %s\n", lockname);
188 return EXIT_FAILURE;
189 }
190
191 if (-1 == flock(lockfd, LOCK_EX)) {
192 fprintf(stderr, "Error locking file %s\n", lockname);
193 close(lockfd);
194 return EXIT_FAILURE;
195 }
196
197 if (strcmp(cmdname, CMD_PRINTENV) == 0) {
Joe Hershberger3f1f1752012-10-03 09:38:49 +0000198 if (fw_printenv(argc, argv) != 0)
199 retval = EXIT_FAILURE;
wdenk34b613e2002-12-17 01:51:00 +0000200 } else if (strcmp(cmdname, CMD_SETENV) == 0) {
Andreas Fenkart33e91772015-12-09 13:13:23 +0100201 if (!setenv_args.script_file) {
Stefano Babicada628b2010-05-24 12:08:16 +0200202 if (fw_setenv(argc, argv) != 0)
Joe Hershberger3f1f1752012-10-03 09:38:49 +0000203 retval = EXIT_FAILURE;
Stefano Babicada628b2010-05-24 12:08:16 +0200204 } else {
Andreas Fenkart33e91772015-12-09 13:13:23 +0100205 if (fw_parse_script(setenv_args.script_file) != 0)
Joe Hershberger3f1f1752012-10-03 09:38:49 +0000206 retval = EXIT_FAILURE;
Stefano Babicada628b2010-05-24 12:08:16 +0200207 }
wdenk34b613e2002-12-17 01:51:00 +0000208 }
209
Joe Hershberger3f1f1752012-10-03 09:38:49 +0000210 flock(lockfd, LOCK_UN);
211 close(lockfd);
212 return retval;
wdenk34b613e2002-12-17 01:51:00 +0000213}