Blame view
env/common.c
6.17 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 |
|
ec8a252cd
|
28 29 30 31 |
/* * Read an environment variable as a boolean * Return -1 if variable does not exist (default to true) */ |
bfebc8c96
|
32 |
int env_get_yesno(const char *var) |
ec8a252cd
|
33 |
{ |
00caae6d4
|
34 |
char *s = env_get(var); |
ec8a252cd
|
35 36 37 38 39 40 |
if (s == NULL) return -1; return (*s == '1' || *s == 'y' || *s == 'Y' || *s == 't' || *s == 'T') ? 1 : 0; } |
267541f77
|
41 42 43 |
/* * Look up the variable from the default environment */ |
723806cc5
|
44 |
char *env_get_default(const char *name) |
267541f77
|
45 46 47 48 49 50 51 |
{ 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; |
2d7cb5b42
|
52 |
gd->env_valid = ENV_INVALID; |
00caae6d4
|
53 |
ret_val = env_get(name); |
267541f77
|
54 55 56 57 |
gd->env_valid = really_valid; gd->flags = real_gd_flags; return ret_val; } |
ea882baf9
|
58 |
void set_default_env(const char *s) |
5bb12dbd7
|
59 |
{ |
c4e0057fa
|
60 |
int flags = 0; |
5bb12dbd7
|
61 |
if (sizeof(default_environment) > ENV_SIZE) { |
ea882baf9
|
62 63 64 |
puts("*** Error - default environment is too large "); |
5bb12dbd7
|
65 66 |
return; } |
ea882baf9
|
67 68 69 70 71 72 |
if (s) { if (*s == '!') { printf("*** Warning - %s, " "using default environment ", |
27aafe988
|
73 |
s + 1); |
ea882baf9
|
74 |
} else { |
c4e0057fa
|
75 |
flags = H_INTERACTIVE; |
ea882baf9
|
76 77 78 |
puts(s); } } else { |
58ae9990c
|
79 80 |
debug("Using default environment "); |
ea882baf9
|
81 |
} |
2eb1573f0
|
82 |
if (himport_r(&env_htab, (char *)default_environment, |
ecd1446fe
|
83 |
sizeof(default_environment), '\0', flags, 0, |
c4e0057fa
|
84 |
0, NULL) == 0) |
9b643e312
|
85 86 |
pr_err("Environment import failed: errno = %d ", errno); |
27aafe988
|
87 |
|
ea882baf9
|
88 |
gd->flags |= GD_FLG_ENV_READY; |
340b0e3bb
|
89 |
gd->flags |= GD_FLG_ENV_DEFAULT; |
5bb12dbd7
|
90 |
} |
b64b7c3df
|
91 92 93 94 95 96 97 98 99 |
/* [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
|
100 |
sizeof(default_environment), '\0', |
ecd1446fe
|
101 |
H_NOCLEAR | H_INTERACTIVE, 0, nvars, vars); |
b64b7c3df
|
102 |
} |
ea882baf9
|
103 104 105 106 107 |
/* * 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
|
108 |
{ |
ea882baf9
|
109 |
env_t *ep = (env_t *)buf; |
05706fddd
|
110 |
|
ea882baf9
|
111 112 113 114 115 116 117 |
if (check) { uint32_t crc; memcpy(&crc, &ep->crc, sizeof(crc)); if (crc32(0, ep->data, ENV_SIZE) != crc) { set_default_env("!bad CRC"); |
42a1820bb
|
118 |
return -EIO; |
ea882baf9
|
119 120 |
} } |
ecd1446fe
|
121 |
if (himport_r(&env_htab, (char *)ep->data, ENV_SIZE, '\0', 0, 0, |
c4e0057fa
|
122 |
0, NULL)) { |
ea882baf9
|
123 |
gd->flags |= GD_FLG_ENV_READY; |
42a1820bb
|
124 |
return 0; |
ea882baf9
|
125 |
} |
05706fddd
|
126 |
|
9b643e312
|
127 128 |
pr_err("Cannot import environment: errno = %d ", errno); |
ea882baf9
|
129 130 |
set_default_env("!import failed"); |
42a1820bb
|
131 |
return -EIO; |
ea882baf9
|
132 |
} |
76768f5f0
|
133 134 |
#ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT static unsigned char env_flags; |
31f044bd9
|
135 136 |
int env_import_redund(const char *buf1, int buf1_read_fail, const char *buf2, int buf2_read_fail) |
76768f5f0
|
137 138 139 140 141 142 |
{ int crc1_ok, crc2_ok; env_t *ep, *tmp_env1, *tmp_env2; tmp_env1 = (env_t *)buf1; tmp_env2 = (env_t *)buf2; |
31f044bd9
|
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 |
if (buf1_read_fail && buf2_read_fail) { puts("*** Error - No Valid Environment Area found "); } else if (buf1_read_fail || buf2_read_fail) { puts("*** Warning - some problems detected "); puts("reading environment; recovered successfully "); } if (buf1_read_fail && buf2_read_fail) { set_default_env("!bad env area"); return -EIO; } else if (!buf1_read_fail && buf2_read_fail) { gd->env_valid = ENV_VALID; return env_import((char *)tmp_env1, 1); } else if (buf1_read_fail && !buf2_read_fail) { gd->env_valid = ENV_REDUND; return env_import((char *)tmp_env2, 1); } |
76768f5f0
|
162 163 164 165 166 167 168 |
crc1_ok = crc32(0, tmp_env1->data, ENV_SIZE) == tmp_env1->crc; crc2_ok = crc32(0, tmp_env2->data, ENV_SIZE) == tmp_env2->crc; if (!crc1_ok && !crc2_ok) { set_default_env("!bad CRC"); |
42a1820bb
|
169 |
return -EIO; |
76768f5f0
|
170 |
} else if (crc1_ok && !crc2_ok) { |
2d7cb5b42
|
171 |
gd->env_valid = ENV_VALID; |
76768f5f0
|
172 |
} else if (!crc1_ok && crc2_ok) { |
2d7cb5b42
|
173 |
gd->env_valid = ENV_REDUND; |
76768f5f0
|
174 175 176 |
} else { /* both ok - check serial */ if (tmp_env1->flags == 255 && tmp_env2->flags == 0) |
2d7cb5b42
|
177 |
gd->env_valid = ENV_REDUND; |
76768f5f0
|
178 |
else if (tmp_env2->flags == 255 && tmp_env1->flags == 0) |
2d7cb5b42
|
179 |
gd->env_valid = ENV_VALID; |
76768f5f0
|
180 |
else if (tmp_env1->flags > tmp_env2->flags) |
2d7cb5b42
|
181 |
gd->env_valid = ENV_VALID; |
76768f5f0
|
182 |
else if (tmp_env2->flags > tmp_env1->flags) |
2d7cb5b42
|
183 |
gd->env_valid = ENV_REDUND; |
76768f5f0
|
184 |
else /* flags are equal - almost impossible */ |
2d7cb5b42
|
185 |
gd->env_valid = ENV_VALID; |
76768f5f0
|
186 |
} |
2d7cb5b42
|
187 |
if (gd->env_valid == ENV_VALID) |
76768f5f0
|
188 189 190 191 192 193 194 195 |
ep = tmp_env1; else ep = tmp_env2; env_flags = ep->flags; return env_import((char *)ep, 0); } #endif /* CONFIG_SYS_REDUNDAND_ENVIRONMENT */ |
fc0b5948e
|
196 |
/* Export the environment and generate CRC for it. */ |
7ce1526ed
|
197 198 199 200 201 202 203 204 |
int env_export(env_t *env_out) { char *res; ssize_t len; res = (char *)env_out->data; len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL); if (len < 0) { |
9b643e312
|
205 206 |
pr_err("Cannot export environment: errno = %d ", errno); |
7ce1526ed
|
207 208 |
return 1; } |
a4223b746
|
209 |
|
7ce1526ed
|
210 |
env_out->crc = crc32(0, env_out->data, ENV_SIZE); |
76768f5f0
|
211 212 213 |
#ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT env_out->flags = ++env_flags; /* increase the serial */ #endif |
7ce1526ed
|
214 215 |
return 0; } |
27aafe988
|
216 |
void env_relocate(void) |
ea882baf9
|
217 |
{ |
2e5167cca
|
218 |
#if defined(CONFIG_NEEDS_MANUAL_RELOC) |
60f7da1f4
|
219 |
env_reloc(); |
7afcf3a55
|
220 |
env_htab.change_ok += gd->reloc_off; |
60f7da1f4
|
221 |
#endif |
2d7cb5b42
|
222 |
if (gd->env_valid == ENV_INVALID) { |
7ac2fe2da
|
223 224 |
#if defined(CONFIG_ENV_IS_NOWHERE) || defined(CONFIG_SPL_BUILD) /* Environment not changable */ |
ea882baf9
|
225 |
set_default_env(NULL); |
05706fddd
|
226 |
#else |
770605e4f
|
227 |
bootstage_error(BOOTSTAGE_ID_NET_CHECKSUM); |
ea882baf9
|
228 |
set_default_env("!bad CRC"); |
d259079d6
|
229 |
#endif |
ea882baf9
|
230 |
} else { |
310fb14b2
|
231 |
env_load(); |
05706fddd
|
232 |
} |
05706fddd
|
233 |
} |
04a85b3b3
|
234 |
|
7ac2fe2da
|
235 |
#if defined(CONFIG_AUTO_COMPLETE) && !defined(CONFIG_SPL_BUILD) |
04a85b3b3
|
236 237 |
int env_complete(char *var, int maxv, char *cmdv[], int bufsz, char *buf) { |
560d424b6
|
238 239 |
ENTRY *match; int found, idx; |
04a85b3b3
|
240 |
|
560d424b6
|
241 |
idx = 0; |
04a85b3b3
|
242 243 |
found = 0; cmdv[0] = NULL; |
560d424b6
|
244 245 |
while ((idx = hmatch_r(var, idx, &match, &env_htab))) { int vallen = strlen(match->key) + 1; |
04a85b3b3
|
246 |
|
560d424b6
|
247 |
if (found >= maxv - 2 || bufsz < vallen) |
04a85b3b3
|
248 |
break; |
560d424b6
|
249 |
|
04a85b3b3
|
250 |
cmdv[found++] = buf; |
560d424b6
|
251 252 253 |
memcpy(buf, match->key, vallen); buf += vallen; bufsz -= vallen; |
04a85b3b3
|
254 |
} |
560d424b6
|
255 256 257 258 |
qsort(cmdv, found, sizeof(cmdv[0]), strcmp_compar); if (idx) cmdv[found++] = "..."; |
27aafe988
|
259 |
|
04a85b3b3
|
260 261 262 263 |
cmdv[found] = NULL; return found; } #endif |