X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=env%2Fcommon.c;h=1fd1bd01d3bb159aa1c4bcad1d317996b658231b;hb=427da6f0280ba1ce07e06941dd18a435fabd18fb;hp=8167ea299264427248a57f9f2f930df752d18c89;hpb=76cc372879e2f2f0467e8a3875f097d189647793;p=oweals%2Fu-boot.git diff --git a/env/common.c b/env/common.c index 8167ea2992..1fd1bd01d3 100644 --- a/env/common.c +++ b/env/common.c @@ -1,20 +1,22 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * (C) Copyright 2000-2010 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH * Andreas Heppel - * - * SPDX-License-Identifier: GPL-2.0+ */ #include #include -#include +#include +#include +#include #include #include #include #include +#include DECLARE_GLOBAL_DATA_PTR; @@ -59,32 +61,29 @@ char *env_get_default(const char *name) return ret_val; } -void set_default_env(const char *s) +void env_set_default(const char *s, int flags) { - int flags = 0; - if (sizeof(default_environment) > ENV_SIZE) { puts("*** Error - default environment is too large\n\n"); return; } if (s) { - if (*s == '!') { + if ((flags & H_INTERACTIVE) == 0) { printf("*** Warning - %s, " - "using default environment\n\n", - s + 1); + "using default environment\n\n", s); } else { - flags = H_INTERACTIVE; puts(s); } } else { - puts("Using default environment\n\n"); + debug("Using default environment\n"); } if (himport_r(&env_htab, (char *)default_environment, sizeof(default_environment), '\0', flags, 0, 0, NULL) == 0) - pr_err("Environment import failed: errno = %d\n", errno); + pr_err("## Error: Environment import failed: errno = %d\n", + errno); gd->flags |= GD_FLG_ENV_READY; gd->flags |= GD_FLG_ENV_DEFAULT; @@ -92,15 +91,16 @@ void set_default_env(const char *s) /* [re]set individual variables to their value in the default environment */ -int set_default_vars(int nvars, char * const vars[]) +int env_set_default_vars(int nvars, char * const vars[], int flags) { /* * Special use-case: import from default environment * (and use \0 as a separator) */ + flags |= H_NOCLEAR; return himport_r(&env_htab, (const char *)default_environment, sizeof(default_environment), '\0', - H_NOCLEAR | H_INTERACTIVE, 0, nvars, vars); + flags, 0, nvars, vars); } /* @@ -117,28 +117,29 @@ int env_import(const char *buf, int check) memcpy(&crc, &ep->crc, sizeof(crc)); if (crc32(0, ep->data, ENV_SIZE) != crc) { - set_default_env("!bad CRC"); - return 0; + env_set_default("bad CRC", 0); + return -ENOMSG; /* needed for env_load() */ } } if (himport_r(&env_htab, (char *)ep->data, ENV_SIZE, '\0', 0, 0, 0, NULL)) { gd->flags |= GD_FLG_ENV_READY; - return 1; + return 0; } pr_err("Cannot import environment: errno = %d\n", errno); - set_default_env("!import failed"); + env_set_default("import failed", 0); - return 0; + return -EIO; } #ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT static unsigned char env_flags; -int env_import_redund(const char *buf1, const char *buf2) +int env_import_redund(const char *buf1, int buf1_read_fail, + const char *buf2, int buf2_read_fail) { int crc1_ok, crc2_ok; env_t *ep, *tmp_env1, *tmp_env2; @@ -146,14 +147,32 @@ int env_import_redund(const char *buf1, const char *buf2) tmp_env1 = (env_t *)buf1; tmp_env2 = (env_t *)buf2; + if (buf1_read_fail && buf2_read_fail) { + puts("*** Error - No Valid Environment Area found\n"); + } else if (buf1_read_fail || buf2_read_fail) { + puts("*** Warning - some problems detected "); + puts("reading environment; recovered successfully\n"); + } + + if (buf1_read_fail && buf2_read_fail) { + env_set_default("bad env area", 0); + 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); + } + 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"); - return 0; + env_set_default("bad CRC", 0); + return -ENOMSG; /* needed for env_load() */ } else if (crc1_ok && !crc2_ok) { gd->env_valid = ENV_VALID; } else if (!crc1_ok && crc2_ok) { @@ -208,47 +227,92 @@ void env_relocate(void) { #if defined(CONFIG_NEEDS_MANUAL_RELOC) env_reloc(); + env_fix_drivers(); env_htab.change_ok += gd->reloc_off; #endif if (gd->env_valid == ENV_INVALID) { #if defined(CONFIG_ENV_IS_NOWHERE) || defined(CONFIG_SPL_BUILD) /* Environment not changable */ - set_default_env(NULL); + env_set_default(NULL, 0); #else bootstage_error(BOOTSTAGE_ID_NET_CHECKSUM); - set_default_env("!bad CRC"); + env_set_default("bad CRC", 0); #endif } else { env_load(); } } -#if defined(CONFIG_AUTO_COMPLETE) && !defined(CONFIG_SPL_BUILD) -int env_complete(char *var, int maxv, char *cmdv[], int bufsz, char *buf) +#ifdef CONFIG_AUTO_COMPLETE +int env_complete(char *var, int maxv, char *cmdv[], int bufsz, char *buf, + bool dollar_comp) { - ENTRY *match; + struct env_entry *match; int found, idx; + 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; + } + idx = 0; found = 0; cmdv[0] = NULL; + while ((idx = hmatch_r(var, idx, &match, &env_htab))) { int vallen = strlen(match->key) + 1; - if (found >= maxv - 2 || bufsz < vallen) + if (found >= maxv - 2 || + bufsz < vallen + (dollar_comp ? 3 : 0)) break; cmdv[found++] = buf; + + /* Add the '${' prefix to each var when doing $ completion. */ + if (dollar_comp) { + strcpy(buf, "${"); + buf += 2; + bufsz -= 3; + } + memcpy(buf, match->key, vallen); buf += vallen; bufsz -= vallen; + + 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++; + } } qsort(cmdv, found, sizeof(cmdv[0]), strcmp_compar); if (idx) - cmdv[found++] = "..."; + cmdv[found++] = dollar_comp ? "${...}" : "..."; cmdv[found] = NULL; return found;