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