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