Blame view

env/common.c 7.23 KB
83d290c56   Tom Rini   SPDX: Convert all...
1
  // SPDX-License-Identifier: GPL-2.0+
05706fddd   wdenk   Initial revision
2
  /*
ea882baf9   Wolfgang Denk   New implementatio...
3
   * (C) Copyright 2000-2010
05706fddd   wdenk   Initial revision
4
5
6
7
   * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
   *
   * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
   * Andreas Heppel <aheppel@sysgo.de>
05706fddd   wdenk   Initial revision
8
9
10
11
   */
  
  #include <common.h>
  #include <command.h>
3f989e7b0   Simon Glass   env: Move env_rel...
12
  #include <env.h>
f3998fdc4   Simon Glass   env: Rename envir...
13
  #include <env_internal.h>
8bef79bf3   Simon Glass   common: Move sort...
14
  #include <sort.h>
05706fddd   wdenk   Initial revision
15
  #include <linux/stddef.h>
ea882baf9   Wolfgang Denk   New implementatio...
16
17
  #include <search.h>
  #include <errno.h>
05706fddd   wdenk   Initial revision
18
  #include <malloc.h>
3db711085   Simon Glass   crc32: Use the cr...
19
  #include <u-boot/crc.h>
05706fddd   wdenk   Initial revision
20

d87080b72   Wolfgang Denk   GCC-4.x fixes: cl...
21
  DECLARE_GLOBAL_DATA_PTR;
05706fddd   wdenk   Initial revision
22
23
24
  /************************************************************************
   * Default settings to be used when no valid environment is found
   */
ddd8418f7   Joe Hershberger   env: cosmetic: Co...
25
  #include <env_default.h>
05706fddd   wdenk   Initial revision
26

c5983592e   Gerlando Falauto   env: add check/ap...
27
  struct hsearch_data env_htab = {
2598090b7   Joe Hershberger   env: Add environm...
28
  	.change_ok = env_flags_validate,
c5983592e   Gerlando Falauto   env: add check/ap...
29
  };
2eb1573f0   Mike Frysinger   hashtable: drop a...
30

ec8a252cd   Joe Hershberger   env: Use getenv_y...
31
32
33
34
  /*
   * Read an environment variable as a boolean
   * Return -1 if variable does not exist (default to true)
   */
bfebc8c96   Simon Glass   env: Rename geten...
35
  int env_get_yesno(const char *var)
ec8a252cd   Joe Hershberger   env: Use getenv_y...
36
  {
00caae6d4   Simon Glass   env: Rename geten...
37
  	char *s = env_get(var);
ec8a252cd   Joe Hershberger   env: Use getenv_y...
38
39
40
41
42
43
  
  	if (s == NULL)
  		return -1;
  	return (*s == '1' || *s == 'y' || *s == 'Y' || *s == 't' || *s == 'T') ?
  		1 : 0;
  }
267541f77   Joe Hershberger   env: Add support ...
44
45
46
  /*
   * Look up the variable from the default environment
   */
723806cc5   Simon Glass   env: Rename some ...
47
  char *env_get_default(const char *name)
267541f77   Joe Hershberger   env: Add support ...
48
49
50
51
52
53
54
  {
  	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   Simon Glass   env: Replace all ...
55
  	gd->env_valid = ENV_INVALID;
00caae6d4   Simon Glass   env: Rename geten...
56
  	ret_val = env_get(name);
267541f77   Joe Hershberger   env: Add support ...
57
58
59
60
  	gd->env_valid = really_valid;
  	gd->flags = real_gd_flags;
  	return ret_val;
  }
0ac7d722e   Simon Glass   env: Move get/set...
61
  void env_set_default(const char *s, int flags)
5bb12dbd7   Harald Welte   Remove code dupli...
62
63
  {
  	if (sizeof(default_environment) > ENV_SIZE) {
ea882baf9   Wolfgang Denk   New implementatio...
64
65
66
  		puts("*** Error - default environment is too large
  
  ");
5bb12dbd7   Harald Welte   Remove code dupli...
67
68
  		return;
  	}
ea882baf9   Wolfgang Denk   New implementatio...
69
  	if (s) {
c5d548a9f   Yaniv Levinsky   env: common: acce...
70
  		if ((flags & H_INTERACTIVE) == 0) {
ea882baf9   Wolfgang Denk   New implementatio...
71
  			printf("*** Warning - %s, "
c5d548a9f   Yaniv Levinsky   env: common: acce...
72
73
74
  				"using default environment
  
  ", s);
ea882baf9   Wolfgang Denk   New implementatio...
75
76
77
78
  		} else {
  			puts(s);
  		}
  	} else {
58ae9990c   Maxime Ripard   env: common: Make...
79
80
  		debug("Using default environment
  ");
ea882baf9   Wolfgang Denk   New implementatio...
81
  	}
2eb1573f0   Mike Frysinger   hashtable: drop a...
82
  	if (himport_r(&env_htab, (char *)default_environment,
ecd1446fe   Alexander Holler   Add option -r to ...
83
  			sizeof(default_environment), '\0', flags, 0,
c4e0057fa   Joe Hershberger   env: Refactor do_...
84
  			0, NULL) == 0)
6c90f6233   Quentin Schulz   env: add the same...
85
86
87
  		pr_err("## Error: Environment import failed: errno = %d
  ",
  		       errno);
27aafe988   Igor Grinberg   env: clean env_co...
88

ea882baf9   Wolfgang Denk   New implementatio...
89
  	gd->flags |= GD_FLG_ENV_READY;
340b0e3bb   Michal Simek   env: Setup GD_FLG...
90
  	gd->flags |= GD_FLG_ENV_DEFAULT;
5bb12dbd7   Harald Welte   Remove code dupli...
91
  }
b64b7c3df   Gerlando Falauto   env: make "env de...
92
93
  
  /* [re]set individual variables to their value in the default environment */
0b9d8a055   Simon Glass   env: Move set_def...
94
  int env_set_default_vars(int nvars, char * const vars[], int flags)
b64b7c3df   Gerlando Falauto   env: make "env de...
95
96
97
98
99
  {
  	/*
  	 * Special use-case: import from default environment
  	 * (and use \0 as a separator)
  	 */
5a04264ec   Yaniv Levinsky   cmd: nvedit: set ...
100
  	flags |= H_NOCLEAR;
b64b7c3df   Gerlando Falauto   env: make "env de...
101
  	return himport_r(&env_htab, (const char *)default_environment,
c4e0057fa   Joe Hershberger   env: Refactor do_...
102
  				sizeof(default_environment), '\0',
477f8116d   Yaniv Levinsky   cmd: nvedit: prop...
103
  				flags, 0, nvars, vars);
b64b7c3df   Gerlando Falauto   env: make "env de...
104
  }
ea882baf9   Wolfgang Denk   New implementatio...
105
106
107
108
109
  /*
   * 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   wdenk   Initial revision
110
  {
ea882baf9   Wolfgang Denk   New implementatio...
111
  	env_t *ep = (env_t *)buf;
05706fddd   wdenk   Initial revision
112

ea882baf9   Wolfgang Denk   New implementatio...
113
114
115
116
117
118
  	if (check) {
  		uint32_t crc;
  
  		memcpy(&crc, &ep->crc, sizeof(crc));
  
  		if (crc32(0, ep->data, ENV_SIZE) != crc) {
0ac7d722e   Simon Glass   env: Move get/set...
119
  			env_set_default("bad CRC", 0);
49d04c589   Sam Protsenko   env: common: Retu...
120
  			return -ENOMSG; /* needed for env_load() */
ea882baf9   Wolfgang Denk   New implementatio...
121
122
  		}
  	}
ecd1446fe   Alexander Holler   Add option -r to ...
123
  	if (himport_r(&env_htab, (char *)ep->data, ENV_SIZE, '\0', 0, 0,
c4e0057fa   Joe Hershberger   env: Refactor do_...
124
  			0, NULL)) {
ea882baf9   Wolfgang Denk   New implementatio...
125
  		gd->flags |= GD_FLG_ENV_READY;
42a1820bb   Simon Goldschmidt   env: make env_imp...
126
  		return 0;
ea882baf9   Wolfgang Denk   New implementatio...
127
  	}
05706fddd   wdenk   Initial revision
128

9b643e312   Masahiro Yamada   treewide: replace...
129
130
  	pr_err("Cannot import environment: errno = %d
  ", errno);
ea882baf9   Wolfgang Denk   New implementatio...
131

0ac7d722e   Simon Glass   env: Move get/set...
132
  	env_set_default("import failed", 0);
ea882baf9   Wolfgang Denk   New implementatio...
133

42a1820bb   Simon Goldschmidt   env: make env_imp...
134
  	return -EIO;
ea882baf9   Wolfgang Denk   New implementatio...
135
  }
76768f5f0   Fiach Antaw   env: Add generic ...
136
137
  #ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT
  static unsigned char env_flags;
31f044bd9   Simon Goldschmidt   env: move more co...
138
139
  int env_import_redund(const char *buf1, int buf1_read_fail,
  		      const char *buf2, int buf2_read_fail)
76768f5f0   Fiach Antaw   env: Add generic ...
140
141
142
143
144
145
  {
  	int crc1_ok, crc2_ok;
  	env_t *ep, *tmp_env1, *tmp_env2;
  
  	tmp_env1 = (env_t *)buf1;
  	tmp_env2 = (env_t *)buf2;
31f044bd9   Simon Goldschmidt   env: move more co...
146
147
148
149
150
151
152
153
154
155
  	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) {
0ac7d722e   Simon Glass   env: Move get/set...
156
  		env_set_default("bad env area", 0);
31f044bd9   Simon Goldschmidt   env: move more co...
157
158
159
160
161
162
163
164
  		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   Fiach Antaw   env: Add generic ...
165
166
167
168
169
170
  	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) {
0ac7d722e   Simon Glass   env: Move get/set...
171
  		env_set_default("bad CRC", 0);
49d04c589   Sam Protsenko   env: common: Retu...
172
  		return -ENOMSG; /* needed for env_load() */
76768f5f0   Fiach Antaw   env: Add generic ...
173
  	} else if (crc1_ok && !crc2_ok) {
2d7cb5b42   Simon Glass   env: Replace all ...
174
  		gd->env_valid = ENV_VALID;
76768f5f0   Fiach Antaw   env: Add generic ...
175
  	} else if (!crc1_ok && crc2_ok) {
2d7cb5b42   Simon Glass   env: Replace all ...
176
  		gd->env_valid = ENV_REDUND;
76768f5f0   Fiach Antaw   env: Add generic ...
177
178
179
  	} else {
  		/* both ok - check serial */
  		if (tmp_env1->flags == 255 && tmp_env2->flags == 0)
2d7cb5b42   Simon Glass   env: Replace all ...
180
  			gd->env_valid = ENV_REDUND;
76768f5f0   Fiach Antaw   env: Add generic ...
181
  		else if (tmp_env2->flags == 255 && tmp_env1->flags == 0)
2d7cb5b42   Simon Glass   env: Replace all ...
182
  			gd->env_valid = ENV_VALID;
76768f5f0   Fiach Antaw   env: Add generic ...
183
  		else if (tmp_env1->flags > tmp_env2->flags)
2d7cb5b42   Simon Glass   env: Replace all ...
184
  			gd->env_valid = ENV_VALID;
76768f5f0   Fiach Antaw   env: Add generic ...
185
  		else if (tmp_env2->flags > tmp_env1->flags)
2d7cb5b42   Simon Glass   env: Replace all ...
186
  			gd->env_valid = ENV_REDUND;
76768f5f0   Fiach Antaw   env: Add generic ...
187
  		else /* flags are equal - almost impossible */
2d7cb5b42   Simon Glass   env: Replace all ...
188
  			gd->env_valid = ENV_VALID;
76768f5f0   Fiach Antaw   env: Add generic ...
189
  	}
2d7cb5b42   Simon Glass   env: Replace all ...
190
  	if (gd->env_valid == ENV_VALID)
76768f5f0   Fiach Antaw   env: Add generic ...
191
192
193
194
195
196
197
198
  		ep = tmp_env1;
  	else
  		ep = tmp_env2;
  
  	env_flags = ep->flags;
  	return env_import((char *)ep, 0);
  }
  #endif /* CONFIG_SYS_REDUNDAND_ENVIRONMENT */
fc0b5948e   Robert P. J. Day   Various, accumula...
199
  /* Export the environment and generate CRC for it. */
7ce1526ed   Marek Vasut   env: Add env_expo...
200
201
202
203
204
205
206
207
  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   Masahiro Yamada   treewide: replace...
208
209
  		pr_err("Cannot export environment: errno = %d
  ", errno);
7ce1526ed   Marek Vasut   env: Add env_expo...
210
211
  		return 1;
  	}
a4223b746   Marek Vasut   env: Implement su...
212

7ce1526ed   Marek Vasut   env: Add env_expo...
213
  	env_out->crc = crc32(0, env_out->data, ENV_SIZE);
76768f5f0   Fiach Antaw   env: Add generic ...
214
215
216
  #ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT
  	env_out->flags = ++env_flags; /* increase the serial */
  #endif
7ce1526ed   Marek Vasut   env: Add env_expo...
217
218
  	return 0;
  }
27aafe988   Igor Grinberg   env: clean env_co...
219
  void env_relocate(void)
ea882baf9   Wolfgang Denk   New implementatio...
220
  {
2e5167cca   Wolfgang Denk   Replace CONFIG_RE...
221
  #if defined(CONFIG_NEEDS_MANUAL_RELOC)
60f7da1f4   Heiko Schocher   env: fix cmd_env_...
222
  	env_reloc();
7bcdf1957   Siva Durga Prasad Paladugu   env: Relocate env...
223
  	env_fix_drivers();
d90fc9c3d   Tom Rini   Revert "env: solv...
224
  	env_htab.change_ok += gd->reloc_off;
60f7da1f4   Heiko Schocher   env: fix cmd_env_...
225
  #endif
2d7cb5b42   Simon Glass   env: Replace all ...
226
  	if (gd->env_valid == ENV_INVALID) {
7ac2fe2da   Ilya Yanok   OMAP: networking ...
227
228
  #if defined(CONFIG_ENV_IS_NOWHERE) || defined(CONFIG_SPL_BUILD)
  		/* Environment not changable */
0ac7d722e   Simon Glass   env: Move get/set...
229
  		env_set_default(NULL, 0);
05706fddd   wdenk   Initial revision
230
  #else
770605e4f   Simon Glass   bootstage: Replac...
231
  		bootstage_error(BOOTSTAGE_ID_NET_CHECKSUM);
0ac7d722e   Simon Glass   env: Move get/set...
232
  		env_set_default("bad CRC", 0);
d259079d6   Lei Wen   env: don't set to...
233
  #endif
ea882baf9   Wolfgang Denk   New implementatio...
234
  	} else {
310fb14b2   Simon Glass   env: Drop env_rel...
235
  		env_load();
05706fddd   wdenk   Initial revision
236
  	}
05706fddd   wdenk   Initial revision
237
  }
04a85b3b3   wdenk   * Patches by Pant...
238

03dcf17db   Boris Brezillon   common: command: ...
239
240
241
  #ifdef CONFIG_AUTO_COMPLETE
  int env_complete(char *var, int maxv, char *cmdv[], int bufsz, char *buf,
  		 bool dollar_comp)
04a85b3b3   wdenk   * Patches by Pant...
242
  {
dd2408cac   Simon Glass   env: Drop the ENT...
243
  	struct env_entry *match;
560d424b6   Mike Frysinger   env: re-add suppo...
244
  	int found, idx;
04a85b3b3   wdenk   * Patches by Pant...
245

03dcf17db   Boris Brezillon   common: command: ...
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
  	if (dollar_comp) {
  		/*
  		 * When doing $ completion, the first character should
  		 * obviously be a '$'.
  		 */
  		if (var[0] != '$')
  			return 0;
  
  		var++;
  
  		/*
  		 * The second one, if present, should be a '{', as some
  		 * configuration of the u-boot shell expand ${var} but not
  		 * $var.
  		 */
  		if (var[0] == '{')
  			var++;
  		else if (var[0] != '\0')
  			return 0;
  	}
560d424b6   Mike Frysinger   env: re-add suppo...
266
  	idx = 0;
04a85b3b3   wdenk   * Patches by Pant...
267
268
  	found = 0;
  	cmdv[0] = NULL;
03dcf17db   Boris Brezillon   common: command: ...
269

560d424b6   Mike Frysinger   env: re-add suppo...
270
271
  	while ((idx = hmatch_r(var, idx, &match, &env_htab))) {
  		int vallen = strlen(match->key) + 1;
04a85b3b3   wdenk   * Patches by Pant...
272

03dcf17db   Boris Brezillon   common: command: ...
273
274
  		if (found >= maxv - 2 ||
  		    bufsz < vallen + (dollar_comp ? 3 : 0))
04a85b3b3   wdenk   * Patches by Pant...
275
  			break;
560d424b6   Mike Frysinger   env: re-add suppo...
276

04a85b3b3   wdenk   * Patches by Pant...
277
  		cmdv[found++] = buf;
03dcf17db   Boris Brezillon   common: command: ...
278
279
280
281
282
283
284
  
  		/* Add the '${' prefix to each var when doing $ completion. */
  		if (dollar_comp) {
  			strcpy(buf, "${");
  			buf += 2;
  			bufsz -= 3;
  		}
560d424b6   Mike Frysinger   env: re-add suppo...
285
286
287
  		memcpy(buf, match->key, vallen);
  		buf += vallen;
  		bufsz -= vallen;
03dcf17db   Boris Brezillon   common: command: ...
288
289
290
291
292
293
294
295
296
297
298
299
  
  		if (dollar_comp) {
  			/*
  			 * This one is a bit odd: vallen already contains the
  			 * '\0' character but we need to add the '}' suffix,
  			 * hence the buf - 1 here. strcpy() will add the '\0'
  			 * character just after '}'. buf is then incremented
  			 * to account for the extra '}' we just added.
  			 */
  			strcpy(buf - 1, "}");
  			buf++;
  		}
04a85b3b3   wdenk   * Patches by Pant...
300
  	}
560d424b6   Mike Frysinger   env: re-add suppo...
301
302
303
  	qsort(cmdv, found, sizeof(cmdv[0]), strcmp_compar);
  
  	if (idx)
03dcf17db   Boris Brezillon   common: command: ...
304
  		cmdv[found++] = dollar_comp ? "${...}" : "...";
27aafe988   Igor Grinberg   env: clean env_co...
305

04a85b3b3   wdenk   * Patches by Pant...
306
307
308
309
  	cmdv[found] = NULL;
  	return found;
  }
  #endif