Blame view

env/common.c 6.17 KB
05706fddd   wdenk   Initial revision
1
  /*
ea882baf9   Wolfgang Denk   New implementatio...
2
   * (C) Copyright 2000-2010
05706fddd   wdenk   Initial revision
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   Wolfgang Denk   New implementatio...
7
   *
3765b3e7b   Wolfgang Denk   Coding Style clea...
8
   * SPDX-License-Identifier:	GPL-2.0+
05706fddd   wdenk   Initial revision
9
10
11
12
13
   */
  
  #include <common.h>
  #include <command.h>
  #include <environment.h>
05706fddd   wdenk   Initial revision
14
  #include <linux/stddef.h>
ea882baf9   Wolfgang Denk   New implementatio...
15
16
  #include <search.h>
  #include <errno.h>
05706fddd   wdenk   Initial revision
17
  #include <malloc.h>
d87080b72   Wolfgang Denk   GCC-4.x fixes: cl...
18
  DECLARE_GLOBAL_DATA_PTR;
05706fddd   wdenk   Initial revision
19
20
21
  /************************************************************************
   * Default settings to be used when no valid environment is found
   */
ddd8418f7   Joe Hershberger   env: cosmetic: Co...
22
  #include <env_default.h>
05706fddd   wdenk   Initial revision
23

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

ec8a252cd   Joe Hershberger   env: Use getenv_y...
28
29
30
31
  /*
   * Read an environment variable as a boolean
   * Return -1 if variable does not exist (default to true)
   */
bfebc8c96   Simon Glass   env: Rename geten...
32
  int env_get_yesno(const char *var)
ec8a252cd   Joe Hershberger   env: Use getenv_y...
33
  {
00caae6d4   Simon Glass   env: Rename geten...
34
  	char *s = env_get(var);
ec8a252cd   Joe Hershberger   env: Use getenv_y...
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   Joe Hershberger   env: Add support ...
41
42
43
  /*
   * Look up the variable from the default environment
   */
723806cc5   Simon Glass   env: Rename some ...
44
  char *env_get_default(const char *name)
267541f77   Joe Hershberger   env: Add support ...
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   Simon Glass   env: Replace all ...
52
  	gd->env_valid = ENV_INVALID;
00caae6d4   Simon Glass   env: Rename geten...
53
  	ret_val = env_get(name);
267541f77   Joe Hershberger   env: Add support ...
54
55
56
57
  	gd->env_valid = really_valid;
  	gd->flags = real_gd_flags;
  	return ret_val;
  }
ea882baf9   Wolfgang Denk   New implementatio...
58
  void set_default_env(const char *s)
5bb12dbd7   Harald Welte   Remove code dupli...
59
  {
c4e0057fa   Joe Hershberger   env: Refactor do_...
60
  	int flags = 0;
5bb12dbd7   Harald Welte   Remove code dupli...
61
  	if (sizeof(default_environment) > ENV_SIZE) {
ea882baf9   Wolfgang Denk   New implementatio...
62
63
64
  		puts("*** Error - default environment is too large
  
  ");
5bb12dbd7   Harald Welte   Remove code dupli...
65
66
  		return;
  	}
ea882baf9   Wolfgang Denk   New implementatio...
67
68
69
70
71
72
  	if (s) {
  		if (*s == '!') {
  			printf("*** Warning - %s, "
  				"using default environment
  
  ",
27aafe988   Igor Grinberg   env: clean env_co...
73
  				s + 1);
ea882baf9   Wolfgang Denk   New implementatio...
74
  		} else {
c4e0057fa   Joe Hershberger   env: Refactor do_...
75
  			flags = H_INTERACTIVE;
ea882baf9   Wolfgang Denk   New implementatio...
76
77
78
  			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)
9b643e312   Masahiro Yamada   treewide: replace...
85
86
  		pr_err("Environment import failed: errno = %d
  ", errno);
27aafe988   Igor Grinberg   env: clean env_co...
87

ea882baf9   Wolfgang Denk   New implementatio...
88
  	gd->flags |= GD_FLG_ENV_READY;
340b0e3bb   Michal Simek   env: Setup GD_FLG...
89
  	gd->flags |= GD_FLG_ENV_DEFAULT;
5bb12dbd7   Harald Welte   Remove code dupli...
90
  }
b64b7c3df   Gerlando Falauto   env: make "env de...
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   Joe Hershberger   env: Refactor do_...
100
  				sizeof(default_environment), '\0',
ecd1446fe   Alexander Holler   Add option -r to ...
101
  				H_NOCLEAR | H_INTERACTIVE, 0, nvars, vars);
b64b7c3df   Gerlando Falauto   env: make "env de...
102
  }
ea882baf9   Wolfgang Denk   New implementatio...
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   wdenk   Initial revision
108
  {
ea882baf9   Wolfgang Denk   New implementatio...
109
  	env_t *ep = (env_t *)buf;
05706fddd   wdenk   Initial revision
110

ea882baf9   Wolfgang Denk   New implementatio...
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   Simon Goldschmidt   env: make env_imp...
118
  			return -EIO;
ea882baf9   Wolfgang Denk   New implementatio...
119
120
  		}
  	}
ecd1446fe   Alexander Holler   Add option -r to ...
121
  	if (himport_r(&env_htab, (char *)ep->data, ENV_SIZE, '\0', 0, 0,
c4e0057fa   Joe Hershberger   env: Refactor do_...
122
  			0, NULL)) {
ea882baf9   Wolfgang Denk   New implementatio...
123
  		gd->flags |= GD_FLG_ENV_READY;
42a1820bb   Simon Goldschmidt   env: make env_imp...
124
  		return 0;
ea882baf9   Wolfgang Denk   New implementatio...
125
  	}
05706fddd   wdenk   Initial revision
126

9b643e312   Masahiro Yamada   treewide: replace...
127
128
  	pr_err("Cannot import environment: errno = %d
  ", errno);
ea882baf9   Wolfgang Denk   New implementatio...
129
130
  
  	set_default_env("!import failed");
42a1820bb   Simon Goldschmidt   env: make env_imp...
131
  	return -EIO;
ea882baf9   Wolfgang Denk   New implementatio...
132
  }
76768f5f0   Fiach Antaw   env: Add generic ...
133
134
  #ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT
  static unsigned char env_flags;
31f044bd9   Simon Goldschmidt   env: move more co...
135
136
  int env_import_redund(const char *buf1, int buf1_read_fail,
  		      const char *buf2, int buf2_read_fail)
76768f5f0   Fiach Antaw   env: Add generic ...
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   Simon Goldschmidt   env: move more co...
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   Fiach Antaw   env: Add generic ...
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   Simon Goldschmidt   env: make env_imp...
169
  		return -EIO;
76768f5f0   Fiach Antaw   env: Add generic ...
170
  	} else if (crc1_ok && !crc2_ok) {
2d7cb5b42   Simon Glass   env: Replace all ...
171
  		gd->env_valid = ENV_VALID;
76768f5f0   Fiach Antaw   env: Add generic ...
172
  	} else if (!crc1_ok && crc2_ok) {
2d7cb5b42   Simon Glass   env: Replace all ...
173
  		gd->env_valid = ENV_REDUND;
76768f5f0   Fiach Antaw   env: Add generic ...
174
175
176
  	} else {
  		/* both ok - check serial */
  		if (tmp_env1->flags == 255 && tmp_env2->flags == 0)
2d7cb5b42   Simon Glass   env: Replace all ...
177
  			gd->env_valid = ENV_REDUND;
76768f5f0   Fiach Antaw   env: Add generic ...
178
  		else if (tmp_env2->flags == 255 && tmp_env1->flags == 0)
2d7cb5b42   Simon Glass   env: Replace all ...
179
  			gd->env_valid = ENV_VALID;
76768f5f0   Fiach Antaw   env: Add generic ...
180
  		else if (tmp_env1->flags > tmp_env2->flags)
2d7cb5b42   Simon Glass   env: Replace all ...
181
  			gd->env_valid = ENV_VALID;
76768f5f0   Fiach Antaw   env: Add generic ...
182
  		else if (tmp_env2->flags > tmp_env1->flags)
2d7cb5b42   Simon Glass   env: Replace all ...
183
  			gd->env_valid = ENV_REDUND;
76768f5f0   Fiach Antaw   env: Add generic ...
184
  		else /* flags are equal - almost impossible */
2d7cb5b42   Simon Glass   env: Replace all ...
185
  			gd->env_valid = ENV_VALID;
76768f5f0   Fiach Antaw   env: Add generic ...
186
  	}
2d7cb5b42   Simon Glass   env: Replace all ...
187
  	if (gd->env_valid == ENV_VALID)
76768f5f0   Fiach Antaw   env: Add generic ...
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   Robert P. J. Day   Various, accumula...
196
  /* Export the environment and generate CRC for it. */
7ce1526ed   Marek Vasut   env: Add env_expo...
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   Masahiro Yamada   treewide: replace...
205
206
  		pr_err("Cannot export environment: errno = %d
  ", errno);
7ce1526ed   Marek Vasut   env: Add env_expo...
207
208
  		return 1;
  	}
a4223b746   Marek Vasut   env: Implement su...
209

7ce1526ed   Marek Vasut   env: Add env_expo...
210
  	env_out->crc = crc32(0, env_out->data, ENV_SIZE);
76768f5f0   Fiach Antaw   env: Add generic ...
211
212
213
  #ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT
  	env_out->flags = ++env_flags; /* increase the serial */
  #endif
7ce1526ed   Marek Vasut   env: Add env_expo...
214
215
  	return 0;
  }
27aafe988   Igor Grinberg   env: clean env_co...
216
  void env_relocate(void)
ea882baf9   Wolfgang Denk   New implementatio...
217
  {
2e5167cca   Wolfgang Denk   Replace CONFIG_RE...
218
  #if defined(CONFIG_NEEDS_MANUAL_RELOC)
60f7da1f4   Heiko Schocher   env: fix cmd_env_...
219
  	env_reloc();
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) {
7ac2fe2da   Ilya Yanok   OMAP: networking ...
223
224
  #if defined(CONFIG_ENV_IS_NOWHERE) || defined(CONFIG_SPL_BUILD)
  		/* Environment not changable */
ea882baf9   Wolfgang Denk   New implementatio...
225
  		set_default_env(NULL);
05706fddd   wdenk   Initial revision
226
  #else
770605e4f   Simon Glass   bootstage: Replac...
227
  		bootstage_error(BOOTSTAGE_ID_NET_CHECKSUM);
ea882baf9   Wolfgang Denk   New implementatio...
228
  		set_default_env("!bad CRC");
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

7ac2fe2da   Ilya Yanok   OMAP: networking ...
235
  #if defined(CONFIG_AUTO_COMPLETE) && !defined(CONFIG_SPL_BUILD)
04a85b3b3   wdenk   * Patches by Pant...
236
237
  int env_complete(char *var, int maxv, char *cmdv[], int bufsz, char *buf)
  {
560d424b6   Mike Frysinger   env: re-add suppo...
238
239
  	ENTRY *match;
  	int found, idx;
04a85b3b3   wdenk   * Patches by Pant...
240

560d424b6   Mike Frysinger   env: re-add suppo...
241
  	idx = 0;
04a85b3b3   wdenk   * Patches by Pant...
242
243
  	found = 0;
  	cmdv[0] = NULL;
560d424b6   Mike Frysinger   env: re-add suppo...
244
245
  	while ((idx = hmatch_r(var, idx, &match, &env_htab))) {
  		int vallen = strlen(match->key) + 1;
04a85b3b3   wdenk   * Patches by Pant...
246

560d424b6   Mike Frysinger   env: re-add suppo...
247
  		if (found >= maxv - 2 || bufsz < vallen)
04a85b3b3   wdenk   * Patches by Pant...
248
  			break;
560d424b6   Mike Frysinger   env: re-add suppo...
249

04a85b3b3   wdenk   * Patches by Pant...
250
  		cmdv[found++] = buf;
560d424b6   Mike Frysinger   env: re-add suppo...
251
252
253
  		memcpy(buf, match->key, vallen);
  		buf += vallen;
  		bufsz -= vallen;
04a85b3b3   wdenk   * Patches by Pant...
254
  	}
560d424b6   Mike Frysinger   env: re-add suppo...
255
256
257
258
  	qsort(cmdv, found, sizeof(cmdv[0]), strcmp_compar);
  
  	if (idx)
  		cmdv[found++] = "...";
27aafe988   Igor Grinberg   env: clean env_co...
259

04a85b3b3   wdenk   * Patches by Pant...
260
261
262
263
  	cmdv[found] = NULL;
  	return found;
  }
  #endif