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