1 /*
2 * (C) Copyright 2000-2010
3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4 *
5 * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
6 * Andreas Heppel <aheppel@sysgo.de>
7 *
8 * SPDX-License-Identifier: GPL-2.0+
9 */
10
11 #include <common.h>
12 #include <command.h>
13 #include <environment.h>
14 #include <linux/stddef.h>
15 #include <search.h>
16 #include <errno.h>
17 #include <malloc.h>
18
19 DECLARE_GLOBAL_DATA_PTR;
20
21 /************************************************************************
22 * Default settings to be used when no valid environment is found
23 */
24 #include <env_default.h>
25
26 struct hsearch_data env_htab = {
27 .change_ok = env_flags_validate,
28 };
29
30 /*
31 * Read an environment variable as a boolean
32 * Return -1 if variable does not exist (default to true)
33 */
env_get_yesno(const char * var)34 int env_get_yesno(const char *var)
35 {
36 char *s = env_get(var);
37
38 if (s == NULL)
39 return -1;
40 return (*s == '1' || *s == 'y' || *s == 'Y' || *s == 't' || *s == 'T') ?
41 1 : 0;
42 }
43
board_env_fixup(void)44 __weak void board_env_fixup(void) {}
45
46 /*
47 * Look up the variable from the default environment
48 */
env_get_default(const char * name)49 char *env_get_default(const char *name)
50 {
51 char *ret_val;
52 unsigned long really_valid = gd->env_valid;
53 unsigned long real_gd_flags = gd->flags;
54
55 /* Pretend that the image is bad. */
56 gd->flags &= ~GD_FLG_ENV_READY;
57 gd->env_valid = ENV_INVALID;
58 ret_val = env_get(name);
59 gd->env_valid = really_valid;
60 gd->flags = real_gd_flags;
61 return ret_val;
62 }
63
set_default_env(const char * s)64 void set_default_env(const char *s)
65 {
66 int flags = 0;
67
68 if (sizeof(default_environment) > ENV_SIZE) {
69 puts("*** Error - default environment is too large\n\n");
70 return;
71 }
72
73 if (s) {
74 if (*s == '!') {
75 printf("*** Warning - %s, "
76 "using default environment\n\n",
77 s + 1);
78 } else {
79 flags = H_INTERACTIVE;
80 puts(s);
81 }
82 } else {
83 puts("Using default environment\n\n");
84 }
85
86 if (himport_r(&env_htab, (char *)default_environment,
87 sizeof(default_environment), '\0', flags, 0,
88 0, NULL) == 0)
89 pr_err("Environment import failed: errno = %d\n", errno);
90
91 gd->flags |= GD_FLG_ENV_READY;
92 gd->flags |= GD_FLG_ENV_DEFAULT;
93
94 board_env_fixup();
95 }
96
97
98 /* [re]set individual variables to their value in the default environment */
set_default_vars(int nvars,char * const vars[])99 int set_default_vars(int nvars, char * const vars[])
100 {
101 /*
102 * Special use-case: import from default environment
103 * (and use \0 as a separator)
104 */
105 return himport_r(&env_htab, (const char *)default_environment,
106 sizeof(default_environment), '\0',
107 H_NOCLEAR | H_INTERACTIVE, 0, nvars, vars);
108 }
109
set_board_env(const char * vars,int size,int flags,bool ready)110 int set_board_env(const char *vars, int size, int flags, bool ready)
111 {
112 if (himport_r(&env_htab, (char *)vars, size, '\0',
113 flags, 0, 0, NULL) == 0) {
114 pr_err("Environment import failed\n");
115 return -1;
116 }
117
118 if (ready) {
119 gd->flags |= GD_FLG_ENV_READY;
120 gd->flags |= GD_FLG_ENV_DEFAULT;
121 }
122
123 return 0;
124 }
125
126 #ifdef CONFIG_ENV_AES
127 #include <uboot_aes.h>
128 /**
129 * env_aes_cbc_get_key() - Get AES-128-CBC key for the environment
130 *
131 * This function shall return 16-byte array containing AES-128 key used
132 * to encrypt and decrypt the environment. This function must be overridden
133 * by the implementer as otherwise the environment encryption will not
134 * work.
135 */
env_aes_cbc_get_key(void)136 __weak uint8_t *env_aes_cbc_get_key(void)
137 {
138 return NULL;
139 }
140
env_aes_cbc_crypt(env_t * env,const int enc)141 static int env_aes_cbc_crypt(env_t *env, const int enc)
142 {
143 unsigned char *data = env->data;
144 uint8_t *key;
145 uint8_t key_exp[AES_EXPAND_KEY_LENGTH];
146 uint32_t aes_blocks;
147
148 key = env_aes_cbc_get_key();
149 if (!key)
150 return -EINVAL;
151
152 /* First we expand the key. */
153 aes_expand_key(key, key_exp);
154
155 /* Calculate the number of AES blocks to encrypt. */
156 aes_blocks = ENV_SIZE / AES_KEY_LENGTH;
157
158 if (enc)
159 aes_cbc_encrypt_blocks(key_exp, data, data, aes_blocks);
160 else
161 aes_cbc_decrypt_blocks(key_exp, data, data, aes_blocks);
162
163 return 0;
164 }
165 #else
env_aes_cbc_crypt(env_t * env,const int enc)166 static inline int env_aes_cbc_crypt(env_t *env, const int enc)
167 {
168 return 0;
169 }
170 #endif
171
172 /*
173 * Check if CRC is valid and (if yes) import the environment.
174 * Note that "buf" may or may not be aligned.
175 */
env_import(const char * buf,int check)176 int env_import(const char *buf, int check)
177 {
178 env_t *ep = (env_t *)buf;
179 int ret;
180
181 if (check) {
182 uint32_t crc;
183
184 memcpy(&crc, &ep->crc, sizeof(crc));
185
186 if (crc32(0, ep->data, ENV_SIZE) != crc) {
187 set_default_env("!bad CRC");
188 return 0;
189 }
190 }
191
192 /* Decrypt the env if desired. */
193 ret = env_aes_cbc_crypt(ep, 0);
194 if (ret) {
195 pr_err("Failed to decrypt env!\n");
196 set_default_env("!import failed");
197 return ret;
198 }
199
200 if (himport_r(&env_htab, (char *)ep->data, ENV_SIZE, '\0', 0, 0,
201 0, NULL)) {
202 gd->flags |= GD_FLG_ENV_READY;
203 return 1;
204 }
205
206 pr_err("Cannot import environment: errno = %d\n", errno);
207
208 set_default_env("!import failed");
209
210 return 0;
211 }
212
213 #ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT
214 static unsigned char env_flags;
215
env_import_redund(const char * buf1,const char * buf2)216 int env_import_redund(const char *buf1, const char *buf2)
217 {
218 int crc1_ok, crc2_ok;
219 env_t *ep, *tmp_env1, *tmp_env2;
220
221 tmp_env1 = (env_t *)buf1;
222 tmp_env2 = (env_t *)buf2;
223
224 crc1_ok = crc32(0, tmp_env1->data, ENV_SIZE) ==
225 tmp_env1->crc;
226 crc2_ok = crc32(0, tmp_env2->data, ENV_SIZE) ==
227 tmp_env2->crc;
228
229 if (!crc1_ok && !crc2_ok) {
230 set_default_env("!bad CRC");
231 return 0;
232 } else if (crc1_ok && !crc2_ok) {
233 gd->env_valid = ENV_VALID;
234 } else if (!crc1_ok && crc2_ok) {
235 gd->env_valid = ENV_REDUND;
236 } else {
237 /* both ok - check serial */
238 if (tmp_env1->flags == 255 && tmp_env2->flags == 0)
239 gd->env_valid = ENV_REDUND;
240 else if (tmp_env2->flags == 255 && tmp_env1->flags == 0)
241 gd->env_valid = ENV_VALID;
242 else if (tmp_env1->flags > tmp_env2->flags)
243 gd->env_valid = ENV_VALID;
244 else if (tmp_env2->flags > tmp_env1->flags)
245 gd->env_valid = ENV_REDUND;
246 else /* flags are equal - almost impossible */
247 gd->env_valid = ENV_VALID;
248 }
249
250 if (gd->env_valid == ENV_VALID)
251 ep = tmp_env1;
252 else
253 ep = tmp_env2;
254
255 env_flags = ep->flags;
256 return env_import((char *)ep, 0);
257 }
258 #endif /* CONFIG_SYS_REDUNDAND_ENVIRONMENT */
259
260 /* Export the environment and generate CRC for it. */
env_export(env_t * env_out)261 int env_export(env_t *env_out)
262 {
263 char *res;
264 ssize_t len;
265 int ret;
266
267 res = (char *)env_out->data;
268 len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
269 if (len < 0) {
270 pr_err("Cannot export environment: errno = %d\n", errno);
271 return 1;
272 }
273
274 /* Encrypt the env if desired. */
275 ret = env_aes_cbc_crypt(env_out, 1);
276 if (ret)
277 return ret;
278
279 env_out->crc = crc32(0, env_out->data, ENV_SIZE);
280
281 #ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT
282 env_out->flags = ++env_flags; /* increase the serial */
283 #endif
284
285 return 0;
286 }
287
env_relocate(void)288 void env_relocate(void)
289 {
290 #if defined(CONFIG_NEEDS_MANUAL_RELOC)
291 env_reloc();
292 env_htab.change_ok += gd->reloc_off;
293 #endif
294 if (gd->env_valid == ENV_INVALID) {
295 #if defined(CONFIG_ENV_IS_NOWHERE) || defined(CONFIG_SPL_BUILD)
296 /* Environment not changable */
297 set_default_env(NULL);
298 #else
299 bootstage_error(BOOTSTAGE_ID_NET_CHECKSUM);
300 set_default_env("!bad CRC");
301 #endif
302 } else {
303 env_load();
304 }
305 }
306
307 #if defined(CONFIG_AUTO_COMPLETE) && !defined(CONFIG_SPL_BUILD)
env_complete(char * var,int maxv,char * cmdv[],int bufsz,char * buf)308 int env_complete(char *var, int maxv, char *cmdv[], int bufsz, char *buf)
309 {
310 ENTRY *match;
311 int found, idx;
312
313 idx = 0;
314 found = 0;
315 cmdv[0] = NULL;
316
317 while ((idx = hmatch_r(var, idx, &match, &env_htab))) {
318 int vallen = strlen(match->key) + 1;
319
320 if (found >= maxv - 2 || bufsz < vallen)
321 break;
322
323 cmdv[found++] = buf;
324 memcpy(buf, match->key, vallen);
325 buf += vallen;
326 bufsz -= vallen;
327 }
328
329 qsort(cmdv, found, sizeof(cmdv[0]), strcmp_compar);
330
331 if (idx)
332 cmdv[found++] = "...";
333
334 cmdv[found] = NULL;
335 return found;
336 }
337 #endif
338