Blame view

env/common.c 7.2 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
12
   */
  
  #include <common.h>
  #include <command.h>
  #include <environment.h>
05706fddd   wdenk   Initial revision
13
  #include <linux/stddef.h>
ea882baf9   Wolfgang Denk   New implementatio...
14
15
  #include <search.h>
  #include <errno.h>
05706fddd   wdenk   Initial revision
16
  #include <malloc.h>
d87080b72   Wolfgang Denk   GCC-4.x fixes: cl...
17
  DECLARE_GLOBAL_DATA_PTR;
05706fddd   wdenk   Initial revision
18
19
20
  /************************************************************************
   * Default settings to be used when no valid environment is found
   */
ddd8418f7   Joe Hershberger   env: cosmetic: Co...
21
  #include <env_default.h>
05706fddd   wdenk   Initial revision
22

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

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

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

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

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

c5d548a9f   Yaniv Levinsky   env: common: acce...
128
  	set_default_env("import failed", 0);
ea882baf9   Wolfgang Denk   New implementatio...
129

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

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

03dcf17db   Boris Brezillon   common: command: ...
235
236
237
  #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...
238
  {
560d424b6   Mike Frysinger   env: re-add suppo...
239
240
  	ENTRY *match;
  	int found, idx;
04a85b3b3   wdenk   * Patches by Pant...
241

03dcf17db   Boris Brezillon   common: command: ...
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
  	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...
262
  	idx = 0;
04a85b3b3   wdenk   * Patches by Pant...
263
264
  	found = 0;
  	cmdv[0] = NULL;
03dcf17db   Boris Brezillon   common: command: ...
265

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

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

04a85b3b3   wdenk   * Patches by Pant...
273
  		cmdv[found++] = buf;
03dcf17db   Boris Brezillon   common: command: ...
274
275
276
277
278
279
280
  
  		/* 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...
281
282
283
  		memcpy(buf, match->key, vallen);
  		buf += vallen;
  		bufsz -= vallen;
03dcf17db   Boris Brezillon   common: command: ...
284
285
286
287
288
289
290
291
292
293
294
295
  
  		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...
296
  	}
560d424b6   Mike Frysinger   env: re-add suppo...
297
298
299
  	qsort(cmdv, found, sizeof(cmdv[0]), strcmp_compar);
  
  	if (idx)
03dcf17db   Boris Brezillon   common: command: ...
300
  		cmdv[found++] = dollar_comp ? "${...}" : "...";
27aafe988   Igor Grinberg   env: clean env_co...
301

04a85b3b3   wdenk   * Patches by Pant...
302
303
304
305
  	cmdv[found] = NULL;
  	return found;
  }
  #endif