Blame view
common/env_common.c
6.16 KB
05706fddd
|
1 |
/* |
ea882baf9
|
2 |
* (C) Copyright 2000-2010 |
05706fddd
|
3 4 5 6 |
* Wolfgang Denk, DENX Software Engineering, wd@denx.de. * * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com> * Andreas Heppel <aheppel@sysgo.de> |
ea882baf9
|
7 |
* |
3765b3e7b
|
8 |
* SPDX-License-Identifier: GPL-2.0+ |
05706fddd
|
9 10 11 12 13 |
*/ #include <common.h> #include <command.h> #include <environment.h> |
05706fddd
|
14 |
#include <linux/stddef.h> |
ea882baf9
|
15 16 |
#include <search.h> #include <errno.h> |
05706fddd
|
17 |
#include <malloc.h> |
d87080b72
|
18 |
DECLARE_GLOBAL_DATA_PTR; |
05706fddd
|
19 20 21 |
/************************************************************************ * Default settings to be used when no valid environment is found */ |
ddd8418f7
|
22 |
#include <env_default.h> |
05706fddd
|
23 |
|
c5983592e
|
24 |
struct hsearch_data env_htab = { |
2598090b7
|
25 |
.change_ok = env_flags_validate, |
c5983592e
|
26 |
}; |
2eb1573f0
|
27 |
|
0b7df6565
|
28 |
__weak uchar env_get_char_spec(int index) |
bf95df44f
|
29 30 31 |
{ return *((uchar *)(gd->env_addr + index)); } |
bf95df44f
|
32 |
|
27aafe988
|
33 |
static uchar env_get_char_init(int index) |
05706fddd
|
34 |
{ |
05706fddd
|
35 36 |
/* if crc was bad, use the default environment */ if (gd->env_valid) |
27aafe988
|
37 |
return env_get_char_spec(index); |
ea882baf9
|
38 |
else |
27aafe988
|
39 |
return default_environment[index]; |
05706fddd
|
40 |
} |
27aafe988
|
41 |
uchar env_get_char_memory(int index) |
05706fddd
|
42 |
{ |
ea882baf9
|
43 |
return *env_get_addr(index); |
05706fddd
|
44 |
} |
27aafe988
|
45 |
uchar env_get_char(int index) |
b502611b5
|
46 |
{ |
b502611b5
|
47 48 |
/* if relocated to RAM */ if (gd->flags & GD_FLG_RELOC) |
27aafe988
|
49 |
return env_get_char_memory(index); |
b502611b5
|
50 |
else |
27aafe988
|
51 |
return env_get_char_init(index); |
b502611b5
|
52 |
} |
27aafe988
|
53 |
const uchar *env_get_addr(int index) |
05706fddd
|
54 |
{ |
ea882baf9
|
55 56 57 58 |
if (gd->env_valid) return (uchar *)(gd->env_addr + index); else return &default_environment[index]; |
05706fddd
|
59 |
} |
ec8a252cd
|
60 61 62 63 64 65 66 67 68 69 70 71 72 |
/* * Read an environment variable as a boolean * Return -1 if variable does not exist (default to true) */ int getenv_yesno(const char *var) { char *s = getenv(var); if (s == NULL) return -1; return (*s == '1' || *s == 'y' || *s == 'Y' || *s == 't' || *s == 'T') ? 1 : 0; } |
267541f77
|
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
/* * Look up the variable from the default environment */ char *getenv_default(const char *name) { char *ret_val; unsigned long really_valid = gd->env_valid; unsigned long real_gd_flags = gd->flags; /* Pretend that the image is bad. */ gd->flags &= ~GD_FLG_ENV_READY; gd->env_valid = 0; ret_val = getenv(name); gd->env_valid = really_valid; gd->flags = real_gd_flags; return ret_val; } |
ea882baf9
|
90 |
void set_default_env(const char *s) |
5bb12dbd7
|
91 |
{ |
c4e0057fa
|
92 |
int flags = 0; |
5bb12dbd7
|
93 |
if (sizeof(default_environment) > ENV_SIZE) { |
ea882baf9
|
94 95 96 |
puts("*** Error - default environment is too large "); |
5bb12dbd7
|
97 98 |
return; } |
ea882baf9
|
99 100 101 102 103 104 |
if (s) { if (*s == '!') { printf("*** Warning - %s, " "using default environment ", |
27aafe988
|
105 |
s + 1); |
ea882baf9
|
106 |
} else { |
c4e0057fa
|
107 |
flags = H_INTERACTIVE; |
ea882baf9
|
108 109 110 111 112 113 114 |
puts(s); } } else { puts("Using default environment "); } |
2eb1573f0
|
115 |
if (himport_r(&env_htab, (char *)default_environment, |
ecd1446fe
|
116 |
sizeof(default_environment), '\0', flags, 0, |
c4e0057fa
|
117 |
0, NULL) == 0) |
ea882baf9
|
118 119 |
error("Environment import failed: errno = %d ", errno); |
27aafe988
|
120 |
|
ea882baf9
|
121 |
gd->flags |= GD_FLG_ENV_READY; |
5bb12dbd7
|
122 |
} |
b64b7c3df
|
123 124 125 126 127 128 129 130 131 |
/* [re]set individual variables to their value in the default environment */ int set_default_vars(int nvars, char * const vars[]) { /* * Special use-case: import from default environment * (and use \0 as a separator) */ return himport_r(&env_htab, (const char *)default_environment, |
c4e0057fa
|
132 |
sizeof(default_environment), '\0', |
ecd1446fe
|
133 |
H_NOCLEAR | H_INTERACTIVE, 0, nvars, vars); |
b64b7c3df
|
134 |
} |
a4223b746
|
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 |
#ifdef CONFIG_ENV_AES #include <aes.h> /** * env_aes_cbc_get_key() - Get AES-128-CBC key for the environment * * This function shall return 16-byte array containing AES-128 key used * to encrypt and decrypt the environment. This function must be overriden * by the implementer as otherwise the environment encryption will not * work. */ __weak uint8_t *env_aes_cbc_get_key(void) { return NULL; } static int env_aes_cbc_crypt(env_t *env, const int enc) { unsigned char *data = env->data; uint8_t *key; uint8_t key_exp[AES_EXPAND_KEY_LENGTH]; uint32_t aes_blocks; key = env_aes_cbc_get_key(); if (!key) return -EINVAL; /* First we expand the key. */ aes_expand_key(key, key_exp); /* Calculate the number of AES blocks to encrypt. */ aes_blocks = ENV_SIZE / AES_KEY_LENGTH; if (enc) aes_cbc_encrypt_blocks(key_exp, data, data, aes_blocks); else aes_cbc_decrypt_blocks(key_exp, data, data, aes_blocks); return 0; } #else static inline int env_aes_cbc_crypt(env_t *env, const int enc) { return 0; } #endif |
ea882baf9
|
180 181 182 183 184 |
/* * Check if CRC is valid and (if yes) import the environment. * Note that "buf" may or may not be aligned. */ int env_import(const char *buf, int check) |
05706fddd
|
185 |
{ |
ea882baf9
|
186 |
env_t *ep = (env_t *)buf; |
a4223b746
|
187 |
int ret; |
05706fddd
|
188 |
|
ea882baf9
|
189 190 191 192 193 194 195 196 197 198 |
if (check) { uint32_t crc; memcpy(&crc, &ep->crc, sizeof(crc)); if (crc32(0, ep->data, ENV_SIZE) != crc) { set_default_env("!bad CRC"); return 0; } } |
a4223b746
|
199 200 201 202 203 204 205 206 |
/* Decrypt the env if desired. */ ret = env_aes_cbc_crypt(ep, 0); if (ret) { error("Failed to decrypt env! "); set_default_env("!import failed"); return ret; } |
ecd1446fe
|
207 |
if (himport_r(&env_htab, (char *)ep->data, ENV_SIZE, '\0', 0, 0, |
c4e0057fa
|
208 |
0, NULL)) { |
ea882baf9
|
209 210 211 |
gd->flags |= GD_FLG_ENV_READY; return 1; } |
05706fddd
|
212 |
|
ea882baf9
|
213 214 215 216 217 218 219 |
error("Cannot import environment: errno = %d ", errno); set_default_env("!import failed"); return 0; } |
7ce1526ed
|
220 221 222 223 224 |
/* Emport the environment and generate CRC for it. */ int env_export(env_t *env_out) { char *res; ssize_t len; |
a4223b746
|
225 |
int ret; |
7ce1526ed
|
226 227 228 229 230 231 232 233 |
res = (char *)env_out->data; len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL); if (len < 0) { error("Cannot export environment: errno = %d ", errno); return 1; } |
a4223b746
|
234 235 236 237 238 |
/* Encrypt the env if desired. */ ret = env_aes_cbc_crypt(env_out, 1); if (ret) return ret; |
7ce1526ed
|
239 240 241 242 |
env_out->crc = crc32(0, env_out->data, ENV_SIZE); return 0; } |
27aafe988
|
243 |
void env_relocate(void) |
ea882baf9
|
244 |
{ |
2e5167cca
|
245 |
#if defined(CONFIG_NEEDS_MANUAL_RELOC) |
60f7da1f4
|
246 |
env_reloc(); |
7afcf3a55
|
247 |
env_htab.change_ok += gd->reloc_off; |
60f7da1f4
|
248 |
#endif |
05706fddd
|
249 |
if (gd->env_valid == 0) { |
7ac2fe2da
|
250 251 |
#if defined(CONFIG_ENV_IS_NOWHERE) || defined(CONFIG_SPL_BUILD) /* Environment not changable */ |
ea882baf9
|
252 |
set_default_env(NULL); |
05706fddd
|
253 |
#else |
770605e4f
|
254 |
bootstage_error(BOOTSTAGE_ID_NET_CHECKSUM); |
ea882baf9
|
255 |
set_default_env("!bad CRC"); |
d259079d6
|
256 |
#endif |
ea882baf9
|
257 |
} else { |
27aafe988
|
258 |
env_relocate_spec(); |
05706fddd
|
259 |
} |
05706fddd
|
260 |
} |
04a85b3b3
|
261 |
|
7ac2fe2da
|
262 |
#if defined(CONFIG_AUTO_COMPLETE) && !defined(CONFIG_SPL_BUILD) |
04a85b3b3
|
263 264 |
int env_complete(char *var, int maxv, char *cmdv[], int bufsz, char *buf) { |
560d424b6
|
265 266 |
ENTRY *match; int found, idx; |
04a85b3b3
|
267 |
|
560d424b6
|
268 |
idx = 0; |
04a85b3b3
|
269 270 |
found = 0; cmdv[0] = NULL; |
560d424b6
|
271 272 |
while ((idx = hmatch_r(var, idx, &match, &env_htab))) { int vallen = strlen(match->key) + 1; |
04a85b3b3
|
273 |
|
560d424b6
|
274 |
if (found >= maxv - 2 || bufsz < vallen) |
04a85b3b3
|
275 |
break; |
560d424b6
|
276 |
|
04a85b3b3
|
277 |
cmdv[found++] = buf; |
560d424b6
|
278 279 280 |
memcpy(buf, match->key, vallen); buf += vallen; bufsz -= vallen; |
04a85b3b3
|
281 |
} |
560d424b6
|
282 283 284 285 |
qsort(cmdv, found, sizeof(cmdv[0]), strcmp_compar); if (idx) cmdv[found++] = "..."; |
27aafe988
|
286 |
|
04a85b3b3
|
287 288 289 290 |
cmdv[found] = NULL; return found; } #endif |