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