Merge branch '2020-07-31-more-env-updates'

- Fix EFI selftest to not force setting serial# environment (and also
  get the U-Boot prompt dynamically).
- Support for append only environment and other related features.
- Improved ext4 environment support
- Fix the case of fw_setenv being used on flash devices that were not
  already locked.
This commit is contained in:
Tom Rini 2020-07-31 10:13:07 -04:00
commit a2d051e7b6
33 changed files with 507 additions and 65 deletions

View File

@ -7,6 +7,7 @@
#include <cpu_func.h>
#include <cros_ec.h>
#include <dm.h>
#include <env_internal.h>
#include <init.h>
#include <led.h>
#include <os.h>
@ -44,6 +45,20 @@ unsigned long timer_read_counter(void)
}
#endif
/* specific order for sandbox: nowhere is the first value, used by default */
static enum env_location env_locations[] = {
ENVL_NOWHERE,
ENVL_EXT4,
};
enum env_location env_get_location(enum env_operation op, int prio)
{
if (prio >= ARRAY_SIZE(env_locations))
return ENVL_UNKNOWN;
return env_locations[prio];
}
int dram_init(void)
{
gd->ram_size = CONFIG_SYS_SDRAM_SIZE;

View File

@ -604,6 +604,17 @@ config CMD_NVEDIT_INFO
[-q] : quiet output
The result of multiple evaluations will be combined with AND.
config CMD_NVEDIT_LOAD
bool "env load"
help
Load all environment variables from the compiled-in persistent
storage.
config CMD_NVEDIT_SELECT
bool "env select"
help
Select the compiled-in persistent storage of environment variables.
endmenu
menu "Memory commands"

View File

@ -794,6 +794,23 @@ U_BOOT_CMD(
);
#endif
#endif
#if defined(CONFIG_CMD_NVEDIT_LOAD)
static int do_env_load(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
{
return env_reload() ? 1 : 0;
}
#endif
#if defined(CONFIG_CMD_NVEDIT_SELECT)
static int do_env_select(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
{
return env_select(argv[1]) ? 1 : 0;
}
#endif
#endif /* CONFIG_SPL_BUILD */
int env_match(uchar *s1, int i2)
@ -1346,6 +1363,9 @@ static struct cmd_tbl cmd_env_sub[] = {
#endif
#if defined(CONFIG_CMD_NVEDIT_INFO)
U_BOOT_CMD_MKENT(info, 3, 0, do_env_info, "", ""),
#endif
#if defined(CONFIG_CMD_NVEDIT_LOAD)
U_BOOT_CMD_MKENT(load, 1, 0, do_env_load, "", ""),
#endif
U_BOOT_CMD_MKENT(print, CONFIG_SYS_MAXARGS, 1, do_env_print, "", ""),
#if defined(CONFIG_CMD_RUN)
@ -1356,6 +1376,9 @@ static struct cmd_tbl cmd_env_sub[] = {
#if defined(CONFIG_CMD_ERASEENV)
U_BOOT_CMD_MKENT(erase, 1, 0, do_env_erase, "", ""),
#endif
#endif
#if defined(CONFIG_CMD_NVEDIT_SELECT)
U_BOOT_CMD_MKENT(select, 2, 0, do_env_select, "", ""),
#endif
U_BOOT_CMD_MKENT(set, CONFIG_SYS_MAXARGS, 0, do_env_set, "", ""),
#if defined(CONFIG_CMD_ENV_EXISTS)
@ -1442,6 +1465,12 @@ static char env_help_text[] =
"env erase - erase environment\n"
#endif
#endif
#if defined(CONFIG_CMD_NVEDIT_LOAD)
"env load - load environment\n"
#endif
#if defined(CONFIG_CMD_NVEDIT_SELECT)
"env select [target] - select environment target\n"
#endif
#if defined(CONFIG_CMD_NVEDIT_EFI)
"env set -e [-nv][-bs][-rt][-at][-a][-i addr,size][-v] name [arg ...]\n"
" - set UEFI variable; unset if '-i' or 'arg' not specified\n"

View File

@ -27,10 +27,13 @@ CONFIG_CMD_BOOTEFI_HELLO=y
# CONFIG_CMD_ELF is not set
CONFIG_CMD_ASKENV=y
CONFIG_CMD_GREPENV=y
CONFIG_CMD_ERASEENV=y
CONFIG_CMD_ENV_CALLBACK=y
CONFIG_CMD_ENV_FLAGS=y
CONFIG_CMD_NVEDIT_EFI=y
CONFIG_CMD_NVEDIT_INFO=y
CONFIG_CMD_NVEDIT_LOAD=y
CONFIG_CMD_NVEDIT_SELECT=y
CONFIG_LOOPW=y
CONFIG_CMD_MD5SUM=y
CONFIG_CMD_MEMINFO=y
@ -83,6 +86,10 @@ CONFIG_OF_CONTROL=y
CONFIG_OF_LIVE=y
CONFIG_OF_HOSTFILE=y
CONFIG_BOOTP_SEND_HOSTNAME=y
CONFIG_ENV_IS_NOWHERE=y
CONFIG_ENV_IS_IN_EXT4=y
CONFIG_ENV_EXT4_INTERFACE="host"
CONFIG_ENV_EXT4_DEVICE_AND_PART="0:0"
CONFIG_NETCONSOLE=y
CONFIG_IP_DEFRAG=y
CONFIG_REGMAP=y

View File

@ -32,10 +32,13 @@ CONFIG_CMD_ABOOTIMG=y
# CONFIG_CMD_ELF is not set
CONFIG_CMD_ASKENV=y
CONFIG_CMD_GREPENV=y
CONFIG_CMD_ERASEENV=y
CONFIG_CMD_ENV_CALLBACK=y
CONFIG_CMD_ENV_FLAGS=y
CONFIG_CMD_NVEDIT_EFI=y
CONFIG_CMD_NVEDIT_INFO=y
CONFIG_CMD_NVEDIT_LOAD=y
CONFIG_CMD_NVEDIT_SELECT=y
CONFIG_LOOPW=y
CONFIG_CMD_MD5SUM=y
CONFIG_CMD_MEMINFO=y
@ -94,6 +97,10 @@ CONFIG_OF_CONTROL=y
CONFIG_OF_LIVE=y
CONFIG_OF_HOSTFILE=y
CONFIG_BOOTP_SEND_HOSTNAME=y
CONFIG_ENV_IS_NOWHERE=y
CONFIG_ENV_IS_IN_EXT4=y
CONFIG_ENV_EXT4_INTERFACE="host"
CONFIG_ENV_EXT4_DEVICE_AND_PART="0:0"
CONFIG_NETCONSOLE=y
CONFIG_IP_DEFRAG=y
CONFIG_REGMAP=y

View File

@ -24,7 +24,10 @@ CONFIG_CMD_BOOTEFI_HELLO=y
# CONFIG_CMD_ELF is not set
CONFIG_CMD_ASKENV=y
CONFIG_CMD_GREPENV=y
CONFIG_CMD_ERASEENV=y
CONFIG_CMD_NVEDIT_INFO=y
CONFIG_CMD_NVEDIT_LOAD=y
CONFIG_CMD_NVEDIT_SELECT=y
CONFIG_LOOPW=y
CONFIG_CMD_MD5SUM=y
CONFIG_CMD_MEMINFO=y
@ -66,6 +69,10 @@ CONFIG_AMIGA_PARTITION=y
CONFIG_OF_CONTROL=y
CONFIG_OF_HOSTFILE=y
CONFIG_BOOTP_SEND_HOSTNAME=y
CONFIG_ENV_IS_NOWHERE=y
CONFIG_ENV_IS_IN_EXT4=y
CONFIG_ENV_EXT4_INTERFACE="host"
CONFIG_ENV_EXT4_DEVICE_AND_PART="0:0"
CONFIG_NETCONSOLE=y
CONFIG_IP_DEFRAG=y
CONFIG_REGMAP=y

View File

@ -34,9 +34,12 @@ CONFIG_CMD_BOOTEFI_HELLO=y
# CONFIG_CMD_ELF is not set
CONFIG_CMD_ASKENV=y
CONFIG_CMD_GREPENV=y
CONFIG_CMD_ERASEENV=y
CONFIG_CMD_ENV_CALLBACK=y
CONFIG_CMD_ENV_FLAGS=y
CONFIG_CMD_NVEDIT_INFO=y
CONFIG_CMD_NVEDIT_LOAD=y
CONFIG_CMD_NVEDIT_SELECT=y
CONFIG_LOOPW=y
CONFIG_CMD_MD5SUM=y
CONFIG_CMD_MEMINFO=y
@ -83,6 +86,10 @@ CONFIG_SPL_OF_CONTROL=y
CONFIG_OF_HOSTFILE=y
CONFIG_SPL_OF_PLATDATA=y
CONFIG_BOOTP_SEND_HOSTNAME=y
CONFIG_ENV_IS_NOWHERE=y
CONFIG_ENV_IS_IN_EXT4=y
CONFIG_ENV_EXT4_INTERFACE="host"
CONFIG_ENV_EXT4_DEVICE_AND_PART="0:0"
CONFIG_NETCONSOLE=y
CONFIG_IP_DEFRAG=y
CONFIG_SPL_DM=y

19
env/Kconfig vendored
View File

@ -479,7 +479,7 @@ config ENV_EXT4_DEVICE_AND_PART
config ENV_EXT4_FILE
string "Name of the EXT4 file to use for the environment"
depends on ENV_IS_IN_EXT4
default "uboot.env"
default "/uboot.env"
help
It's a string of the EXT4 file name. This file use to store the
environment (explicit path to the file)
@ -614,6 +614,23 @@ config DELAY_ENVIRONMENT
later by U-Boot code. With CONFIG_OF_CONTROL this is instead
controlled by the value of /config/load-environment.
config ENV_APPEND
bool "Always append the environment with new data"
default n
help
If defined, the environment hash table is only ever appended with new
data, but the existing hash table can never be dropped and reloaded
with newly imported data. This may be used in combination with static
flags to e.g. to protect variables which must not be modified.
config ENV_WRITEABLE_LIST
bool "Permit write access only to listed variables"
default n
help
If defined, only environment variables which explicitly set the 'w'
writeable flag can be written and modified at runtime. No variables
can be otherwise created, written or imported into the environment.
config ENV_ACCESS_IGNORE_FORCE
bool "Block forced environment operations"
default n

16
env/common.c vendored
View File

@ -81,6 +81,7 @@ void env_set_default(const char *s, int flags)
debug("Using default environment\n");
}
flags |= H_DEFAULT;
if (himport_r(&env_htab, (char *)default_environment,
sizeof(default_environment), '\0', flags, 0,
0, NULL) == 0)
@ -99,7 +100,7 @@ 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;
flags |= H_NOCLEAR | H_DEFAULT;
return himport_r(&env_htab, (const char *)default_environment,
sizeof(default_environment), '\0',
flags, 0, nvars, vars);
@ -109,7 +110,7 @@ int env_set_default_vars(int nvars, char * const vars[], int flags)
* 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)
int env_import(const char *buf, int check, int flags)
{
env_t *ep = (env_t *)buf;
@ -124,7 +125,7 @@ int env_import(const char *buf, int check)
}
}
if (himport_r(&env_htab, (char *)ep->data, ENV_SIZE, '\0', 0, 0,
if (himport_r(&env_htab, (char *)ep->data, ENV_SIZE, '\0', flags, 0,
0, NULL)) {
gd->flags |= GD_FLG_ENV_READY;
return 0;
@ -141,7 +142,8 @@ int env_import(const char *buf, int check)
static unsigned char env_flags;
int env_import_redund(const char *buf1, int buf1_read_fail,
const char *buf2, int buf2_read_fail)
const char *buf2, int buf2_read_fail,
int flags)
{
int crc1_ok, crc2_ok;
env_t *ep, *tmp_env1, *tmp_env2;
@ -161,10 +163,10 @@ int env_import_redund(const char *buf1, int buf1_read_fail,
return -EIO;
} else if (!buf1_read_fail && buf2_read_fail) {
gd->env_valid = ENV_VALID;
return env_import((char *)tmp_env1, 1);
return env_import((char *)tmp_env1, 1, flags);
} else if (buf1_read_fail && !buf2_read_fail) {
gd->env_valid = ENV_REDUND;
return env_import((char *)tmp_env2, 1);
return env_import((char *)tmp_env2, 1, flags);
}
crc1_ok = crc32(0, tmp_env1->data, ENV_SIZE) ==
@ -199,7 +201,7 @@ int env_import_redund(const char *buf1, int buf1_read_fail,
ep = tmp_env2;
env_flags = ep->flags;
return env_import((char *)ep, 0);
return env_import((char *)ep, 0, flags);
}
#endif /* CONFIG_SYS_REDUNDAND_ENVIRONMENT */

2
env/eeprom.c vendored
View File

@ -188,7 +188,7 @@ static int env_eeprom_load(void)
eeprom_bus_read(CONFIG_SYS_DEF_EEPROM_ADDR,
off, (uchar *)buf_env, CONFIG_ENV_SIZE);
return env_import(buf_env, 1);
return env_import(buf_env, 1, H_EXTERNAL);
}
static int env_eeprom_save(void)

82
env/env.c vendored
View File

@ -131,8 +131,6 @@ __weak enum env_location env_get_location(enum env_operation op, int prio)
if (prio >= ARRAY_SIZE(env_locations))
return ENVL_UNKNOWN;
gd->env_load_prio = prio;
return env_locations[prio];
}
@ -189,9 +187,6 @@ int env_load(void)
for (prio = 0; (drv = env_driver_lookup(ENVOP_LOAD, prio)); prio++) {
int ret;
if (!drv->load)
continue;
if (!env_has_inited(drv->location))
continue;
@ -204,7 +199,11 @@ int env_load(void)
ret = drv->load();
if (!ret) {
printf("OK\n");
gd->env_load_prio = prio;
#if !CONFIG_IS_ENABLED(ENV_APPEND)
return 0;
#endif
} else if (ret == -ENOMSG) {
/* Handle "bad CRC" case */
if (best_prio == -1)
@ -227,7 +226,36 @@ int env_load(void)
debug("Selecting environment with bad CRC\n");
else
best_prio = 0;
env_get_location(ENVOP_LOAD, best_prio);
gd->env_load_prio = best_prio;
return -ENODEV;
}
int env_reload(void)
{
struct env_driver *drv;
drv = env_driver_lookup(ENVOP_LOAD, gd->env_load_prio);
if (drv) {
int ret;
printf("Loading Environment from %s... ", drv->name);
if (!env_has_inited(drv->location)) {
printf("not initialized\n");
return -ENODEV;
}
ret = drv->load();
if (ret)
printf("Failed (%d)\n", ret);
else
printf("OK\n");
if (!ret)
return 0;
}
return -ENODEV;
}
@ -318,3 +346,45 @@ int env_init(void)
return ret;
}
int env_select(const char *name)
{
struct env_driver *drv;
const int n_ents = ll_entry_count(struct env_driver, env_driver);
struct env_driver *entry;
int prio;
bool found = false;
printf("Select Environment on %s: ", name);
/* search ENV driver by name */
drv = ll_entry_start(struct env_driver, env_driver);
for (entry = drv; entry != drv + n_ents; entry++) {
if (!strcmp(entry->name, name)) {
found = true;
break;
}
}
if (!found) {
printf("driver not found\n");
return -ENODEV;
}
/* search priority by driver */
for (prio = 0; (drv = env_driver_lookup(ENVOP_INIT, prio)); prio++) {
if (entry->location == env_get_location(ENVOP_LOAD, prio)) {
/* when priority change, reset the ENV flags */
if (gd->env_load_prio != prio) {
gd->env_load_prio = prio;
gd->env_valid = ENV_INVALID;
gd->flags &= ~GD_FLG_ENV_DEFAULT;
}
printf("OK\n");
return 0;
}
}
printf("priority not found\n");
return -ENODEV;
}

54
env/ext4.c vendored
View File

@ -32,6 +32,8 @@
#include <ext4fs.h>
#include <mmc.h>
DECLARE_GLOBAL_DATA_PTR;
__weak const char *env_ext4_get_intf(void)
{
return (const char *)CONFIG_ENV_EXT4_INTERFACE;
@ -42,9 +44,8 @@ __weak const char *env_ext4_get_dev_part(void)
return (const char *)CONFIG_ENV_EXT4_DEVICE_AND_PART;
}
static int env_ext4_save(void)
static int env_ext4_save_buffer(env_t *env_new)
{
env_t env_new;
struct blk_desc *dev_desc = NULL;
struct disk_partition info;
int dev, part;
@ -52,10 +53,6 @@ static int env_ext4_save(void)
const char *ifname = env_ext4_get_intf();
const char *dev_and_part = env_ext4_get_dev_part();
err = env_export(&env_new);
if (err)
return err;
part = blk_get_device_part_str(ifname, dev_and_part,
&dev_desc, &info, 1);
if (part < 0)
@ -70,7 +67,7 @@ static int env_ext4_save(void)
return 1;
}
err = ext4fs_write(CONFIG_ENV_EXT4_FILE, (void *)&env_new,
err = ext4fs_write(CONFIG_ENV_EXT4_FILE, (void *)env_new,
sizeof(env_t), FILETYPE_REG);
ext4fs_close();
@ -80,7 +77,42 @@ static int env_ext4_save(void)
return 1;
}
return 0;
}
static int env_ext4_save(void)
{
env_t env_new;
int err;
err = env_export(&env_new);
if (err)
return err;
err = env_ext4_save_buffer(&env_new);
if (err)
return err;
gd->env_valid = ENV_VALID;
puts("done\n");
return 0;
}
static int env_ext4_erase(void)
{
env_t env_new;
int err;
memset(&env_new, 0, sizeof(env_t));
err = env_ext4_save_buffer(&env_new);
if (err)
return err;
gd->env_valid = ENV_INVALID;
puts("done\n");
return 0;
}
@ -124,7 +156,11 @@ static int env_ext4_load(void)
goto err_env_relocate;
}
return env_import(buf, 1);
err = env_import(buf, 1, H_EXTERNAL);
if (!err)
gd->env_valid = ENV_VALID;
return err;
err_env_relocate:
env_set_default(NULL, 0);
@ -137,4 +173,6 @@ U_BOOT_ENV_LOCATION(ext4) = {
ENV_NAME("EXT4")
.load = env_ext4_load,
.save = ENV_SAVE_PTR(env_ext4_save),
.erase = CONFIG_IS_ENABLED(CMD_ERASEENV) ? env_ext4_erase :
NULL,
};

2
env/fat.c vendored
View File

@ -144,7 +144,7 @@ static int env_fat_load(void)
goto err_env_relocate;
}
return env_import(buf, 1);
return env_import(buf, 1, H_EXTERNAL);
err_env_relocate:
env_set_default(NULL, 0);

66
env/flags.c vendored
View File

@ -28,8 +28,15 @@
#define ENV_FLAGS_NET_VARTYPE_REPS ""
#endif
#ifdef CONFIG_ENV_WRITEABLE_LIST
#define ENV_FLAGS_WRITEABLE_VARACCESS_REPS "w"
#else
#define ENV_FLAGS_WRITEABLE_VARACCESS_REPS ""
#endif
static const char env_flags_vartype_rep[] = "sdxb" ENV_FLAGS_NET_VARTYPE_REPS;
static const char env_flags_varaccess_rep[] = "aroc";
static const char env_flags_varaccess_rep[] =
"aroc" ENV_FLAGS_WRITEABLE_VARACCESS_REPS;
static const int env_flags_varaccess_mask[] = {
0,
ENV_FLAGS_VARACCESS_PREVENT_DELETE |
@ -38,7 +45,11 @@ static const int env_flags_varaccess_mask[] = {
ENV_FLAGS_VARACCESS_PREVENT_DELETE |
ENV_FLAGS_VARACCESS_PREVENT_OVERWR,
ENV_FLAGS_VARACCESS_PREVENT_DELETE |
ENV_FLAGS_VARACCESS_PREVENT_NONDEF_OVERWR};
ENV_FLAGS_VARACCESS_PREVENT_NONDEF_OVERWR,
#ifdef CONFIG_ENV_WRITEABLE_LIST
ENV_FLAGS_VARACCESS_WRITEABLE,
#endif
};
#ifdef CONFIG_CMD_ENV_FLAGS
static const char * const env_flags_vartype_names[] = {
@ -56,6 +67,9 @@ static const char * const env_flags_varaccess_names[] = {
"read-only",
"write-once",
"change-default",
#ifdef CONFIG_ENV_WRITEABLE_LIST
"writeable",
#endif
};
/*
@ -130,21 +144,25 @@ enum env_flags_vartype env_flags_parse_vartype(const char *flags)
*/
enum env_flags_varaccess env_flags_parse_varaccess(const char *flags)
{
enum env_flags_varaccess va_default = env_flags_varaccess_any;
enum env_flags_varaccess va;
char *access;
if (strlen(flags) <= ENV_FLAGS_VARACCESS_LOC)
return env_flags_varaccess_any;
return va_default;
access = strchr(env_flags_varaccess_rep,
flags[ENV_FLAGS_VARACCESS_LOC]);
if (access != NULL)
return (enum env_flags_varaccess)
if (access != NULL) {
va = (enum env_flags_varaccess)
(access - &env_flags_varaccess_rep[0]);
return va;
}
printf("## Warning: Unknown environment variable access method '%c'\n",
flags[ENV_FLAGS_VARACCESS_LOC]);
return env_flags_varaccess_any;
return va_default;
}
/*
@ -152,17 +170,21 @@ enum env_flags_varaccess env_flags_parse_varaccess(const char *flags)
*/
enum env_flags_varaccess env_flags_parse_varaccess_from_binflags(int binflags)
{
enum env_flags_varaccess va_default = env_flags_varaccess_any;
enum env_flags_varaccess va;
int i;
for (i = 0; i < ARRAY_SIZE(env_flags_varaccess_mask); i++)
if (env_flags_varaccess_mask[i] ==
(binflags & ENV_FLAGS_VARACCESS_BIN_MASK))
return (enum env_flags_varaccess)i;
(binflags & ENV_FLAGS_VARACCESS_BIN_MASK)) {
va = (enum env_flags_varaccess)i;
return va;
}
printf("Warning: Non-standard access flags. (0x%x)\n",
binflags & ENV_FLAGS_VARACCESS_BIN_MASK);
return env_flags_varaccess_any;
return va_default;
}
static inline int is_hex_prefix(const char *value)
@ -326,13 +348,14 @@ enum env_flags_vartype env_flags_get_type(const char *name)
enum env_flags_varaccess env_flags_get_varaccess(const char *name)
{
const char *flags_list = env_get(ENV_FLAGS_VAR);
enum env_flags_varaccess va_default = env_flags_varaccess_any;
char flags[ENV_FLAGS_ATTR_MAX_LEN + 1];
if (env_flags_lookup(flags_list, name, flags))
return env_flags_varaccess_any;
return va_default;
if (strlen(flags) <= ENV_FLAGS_VARACCESS_LOC)
return env_flags_varaccess_any;
return va_default;
return env_flags_parse_varaccess(flags);
}
@ -426,7 +449,11 @@ void env_flags_init(struct env_entry *var_entry)
int ret = 1;
if (first_call) {
#ifdef CONFIG_ENV_WRITEABLE_LIST
flags_list = ENV_FLAGS_LIST_STATIC;
#else
flags_list = env_get(ENV_FLAGS_VAR);
#endif
first_call = 0;
}
/* look in the ".flags" and static for a reference to this variable */
@ -523,9 +550,24 @@ int env_flags_validate(const struct env_entry *item, const char *newval,
}
/* check for access permission */
#ifdef CONFIG_ENV_WRITEABLE_LIST
if (flag & H_DEFAULT)
return 0; /* Default env is always OK */
/*
* External writeable variables can be overwritten by external env,
* anything else can not be overwritten by external env.
*/
if ((flag & H_EXTERNAL) &&
!(item->flags & ENV_FLAGS_VARACCESS_WRITEABLE))
return 1;
#endif
#ifndef CONFIG_ENV_ACCESS_IGNORE_FORCE
if (flag & H_FORCE)
if (flag & H_FORCE) {
printf("## Error: Can't force access to \"%s\"\n", name);
return 0;
}
#endif
switch (op) {
case env_op_delete:

2
env/flash.c vendored
View File

@ -351,7 +351,7 @@ static int env_flash_load(void)
"reading environment; recovered successfully\n\n");
#endif /* CONFIG_ENV_ADDR_REDUND */
return env_import((char *)flash_addr, 1);
return env_import((char *)flash_addr, 1, H_EXTERNAL);
}
#endif /* LOADENV */

4
env/mmc.c vendored
View File

@ -338,7 +338,7 @@ static int env_mmc_load(void)
read2_fail = read_env(mmc, CONFIG_ENV_SIZE, offset2, tmp_env2);
ret = env_import_redund((char *)tmp_env1, read1_fail, (char *)tmp_env2,
read2_fail);
read2_fail, H_EXTERNAL);
fini:
fini_mmc_for_env(mmc);
@ -380,7 +380,7 @@ static int env_mmc_load(void)
goto fini;
}
ret = env_import(buf, 1);
ret = env_import(buf, 1, H_EXTERNAL);
if (!ret) {
ep = (env_t *)buf;
gd->env_addr = (ulong)&ep->data;

4
env/nand.c vendored
View File

@ -331,7 +331,7 @@ static int env_nand_load(void)
read2_fail = readenv(CONFIG_ENV_OFFSET_REDUND, (u_char *) tmp_env2);
ret = env_import_redund((char *)tmp_env1, read1_fail, (char *)tmp_env2,
read2_fail);
read2_fail, H_EXTERNAL);
done:
free(tmp_env1);
@ -372,7 +372,7 @@ static int env_nand_load(void)
return -EIO;
}
return env_import(buf, 1);
return env_import(buf, 1, H_EXTERNAL);
#endif /* ! ENV_IS_EMBEDDED */
return 0;

17
env/nowhere.c vendored
View File

@ -27,8 +27,25 @@ static int env_nowhere_init(void)
return 0;
}
static int env_nowhere_load(void)
{
/*
* for SPL, set env_valid = ENV_INVALID is enougth as env_get_char()
* return the default env if env_get is used
* and SPL don't used env_import to reduce its size
* For U-Boot proper, import the default environment to allow reload.
*/
if (!IS_ENABLED(CONFIG_SPL_BUILD))
env_set_default(NULL, 0);
gd->env_valid = ENV_INVALID;
return 0;
}
U_BOOT_ENV_LOCATION(nowhere) = {
.location = ENVL_NOWHERE,
.init = env_nowhere_init,
.load = env_nowhere_load,
ENV_NAME("nowhere")
};

2
env/nvram.c vendored
View File

@ -64,7 +64,7 @@ static int env_nvram_load(void)
#else
memcpy(buf, (void *)CONFIG_ENV_ADDR, CONFIG_ENV_SIZE);
#endif
return env_import(buf, 1);
return env_import(buf, 1, H_EXTERNAL);
}
static int env_nvram_save(void)

2
env/onenand.c vendored
View File

@ -55,7 +55,7 @@ static int env_onenand_load(void)
mtd->writesize = MAX_ONENAND_PAGESIZE;
#endif /* !ENV_IS_EMBEDDED */
rc = env_import(buf, 1);
rc = env_import(buf, 1, H_EXTERNAL);
if (!rc)
gd->env_valid = ENV_VALID;

2
env/remote.c vendored
View File

@ -45,7 +45,7 @@ static int env_remote_save(void)
static int env_remote_load(void)
{
#ifndef ENV_IS_EMBEDDED
return env_import((char *)env_ptr, 1);
return env_import((char *)env_ptr, 1, H_EXTERNAL);
#endif
return 0;

2
env/sata.c vendored
View File

@ -111,7 +111,7 @@ static void env_sata_load(void)
return -EIO;
}
return env_import(buf, 1);
return env_import(buf, 1, H_EXTERNAL);
}
U_BOOT_ENV_LOCATION(sata) = {

6
env/sf.c vendored
View File

@ -172,7 +172,7 @@ static int env_sf_load(void)
CONFIG_ENV_SIZE, tmp_env2);
ret = env_import_redund((char *)tmp_env1, read1_fail, (char *)tmp_env2,
read2_fail);
read2_fail, H_EXTERNAL);
spi_flash_free(env_flash);
env_flash = NULL;
@ -265,7 +265,7 @@ static int env_sf_load(void)
goto err_read;
}
ret = env_import(buf, 1);
ret = env_import(buf, 1, H_EXTERNAL);
if (!ret)
gd->env_valid = ENV_VALID;
@ -305,7 +305,7 @@ static int env_sf_init(void)
U_BOOT_ENV_LOCATION(sf) = {
.location = ENVL_SPI_FLASH,
ENV_NAME("SPI Flash")
ENV_NAME("SPIFlash")
.load = env_sf_load,
.save = CONFIG_IS_ENABLED(SAVEENV) ? ENV_SAVE_PTR(env_sf_save) : NULL,
#if defined(INITENV) && (CONFIG_ENV_ADDR != 0x0)

4
env/ubi.c vendored
View File

@ -141,7 +141,7 @@ static int env_ubi_load(void)
CONFIG_ENV_UBI_PART, CONFIG_ENV_UBI_VOLUME_REDUND);
return env_import_redund((char *)tmp_env1, read1_fail, (char *)tmp_env2,
read2_fail);
read2_fail, H_EXTERNAL);
}
#else /* ! CONFIG_SYS_REDUNDAND_ENVIRONMENT */
static int env_ubi_load(void)
@ -172,7 +172,7 @@ static int env_ubi_load(void)
return -EIO;
}
return env_import(buf, 1);
return env_import(buf, 1, H_EXTERNAL);
}
#endif /* CONFIG_SYS_REDUNDAND_ENVIRONMENT */

View File

@ -265,6 +265,13 @@ int env_set_default_vars(int nvars, char *const vars[], int flags);
*/
int env_load(void);
/**
* env_reload() - Re-Load the environment from current storage
*
* @return 0 if OK, -ve on error
*/
int env_reload(void);
/**
* env_save() - Save the environment to storage
*
@ -279,6 +286,13 @@ int env_save(void);
*/
int env_erase(void);
/**
* env_select() - Select the environment storage
*
* @return 0 if OK, -ve on error
*/
int env_select(const char *name);
/**
* env_import() - Import from a binary representation into hash table
*
@ -288,10 +302,11 @@ int env_erase(void);
* @buf: Buffer containing the environment (struct environemnt_s *)
* @check: non-zero to check the CRC at the start of the environment, 0 to
* ignore it
* @flags: Flags controlling matching (H_... - see search.h)
* @return 0 if imported successfully, -ENOMSG if the CRC was bad, -EIO if
* something else went wrong
*/
int env_import(const char *buf, int check);
int env_import(const char *buf, int check, int flags);
/**
* env_export() - Export the environment to a buffer
@ -310,10 +325,12 @@ int env_export(struct environment_s *env_out);
* @buf1_read_fail: 0 if buf1 is valid, non-zero if invalid
* @buf2: Second environment (struct environemnt_s *)
* @buf2_read_fail: 0 if buf2 is valid, non-zero if invalid
* @flags: Flags controlling matching (H_... - see search.h)
* @return 0 if OK, -EIO if no environment is valid, -ENOMSG if the CRC was bad
*/
int env_import_redund(const char *buf1, int buf1_read_fail,
const char *buf2, int buf2_read_fail);
const char *buf2, int buf2_read_fail,
int flags);
/**
* env_get_default() - Look up a variable from the default environment
@ -342,5 +359,4 @@ int env_get_char(int index);
* This is used for those unfortunate archs with crappy toolchains
*/
void env_reloc(void);
#endif

View File

@ -24,6 +24,9 @@ enum env_flags_varaccess {
env_flags_varaccess_readonly,
env_flags_varaccess_writeonce,
env_flags_varaccess_changedefault,
#ifdef CONFIG_ENV_WRITEABLE_LIST
env_flags_varaccess_writeable,
#endif
env_flags_varaccess_end
};
@ -173,6 +176,7 @@ int env_flags_validate(const struct env_entry *item, const char *newval,
#define ENV_FLAGS_VARACCESS_PREVENT_CREATE 0x00000010
#define ENV_FLAGS_VARACCESS_PREVENT_OVERWR 0x00000020
#define ENV_FLAGS_VARACCESS_PREVENT_NONDEF_OVERWR 0x00000040
#define ENV_FLAGS_VARACCESS_BIN_MASK 0x00000078
#define ENV_FLAGS_VARACCESS_WRITEABLE 0x00000080
#define ENV_FLAGS_VARACCESS_BIN_MASK 0x000000f8
#endif /* __ENV_FLAGS_H__ */

View File

@ -154,8 +154,7 @@ struct env_driver {
/**
* load() - Load the environment from storage
*
* This method is optional. If not provided, no environment will be
* loaded.
* This method is required for loading environment
*
* @return 0 if OK, -ve on error
*/
@ -211,6 +210,26 @@ struct env_driver {
extern struct hsearch_data env_htab;
/**
* env_ext4_get_intf() - Provide the interface for env in EXT4
*
* It is a weak function allowing board to overidde the default interface for
* U-Boot env in EXT4: CONFIG_ENV_EXT4_INTERFACE
*
* @return string of interface, empty if not supported
*/
const char *env_ext4_get_intf(void);
/**
* env_ext4_get_dev_part() - Provide the device and partition for env in EXT4
*
* It is a weak function allowing board to overidde the default device and
* partition used for U-Boot env in EXT4: CONFIG_ENV_EXT4_DEVICE_AND_PART
*
* @return string of device and partition
*/
const char *env_ext4_get_dev_part(void);
/**
* env_get_location()- Provide the best location for the U-Boot environment
*

View File

@ -112,5 +112,7 @@ int hwalk_r(struct hsearch_data *htab,
#define H_MATCH_METHOD (H_MATCH_IDENT | H_MATCH_SUBSTR | H_MATCH_REGEX)
#define H_PROGRAMMATIC (1 << 9) /* indicate that an import is from env_set() */
#define H_ORIGIN_FLAGS (H_INTERACTIVE | H_PROGRAMMATIC)
#define H_DEFAULT (1 << 10) /* indicate that an import is default env */
#define H_EXTERNAL (1 << 11) /* indicate that an import is external env */
#endif /* _SEARCH_H_ */

View File

@ -826,6 +826,10 @@ int himport_r(struct hsearch_data *htab,
if (nvars)
memcpy(localvars, vars, sizeof(vars[0]) * nvars);
#if CONFIG_IS_ENABLED(ENV_APPEND)
flag |= H_NOCLEAR;
#endif
if ((flag & H_NOCLEAR) == 0 && !nvars) {
/* Destroy old hash table if one exists */
debug("Destroy Hash Table: %p table = %p\n", htab,
@ -946,9 +950,12 @@ int himport_r(struct hsearch_data *htab,
e.data = value;
hsearch_r(e, ENV_ENTER, &rv, htab, flag);
if (rv == NULL)
#if !CONFIG_IS_ENABLED(ENV_WRITEABLE_LIST)
if (rv == NULL) {
printf("himport_r: can't insert \"%s=%s\" into hash table\n",
name, value);
}
#endif
debug("INSERT: table %p, filled %d/%d rv %p ==> name=\"%s\" value=\"%s\"\n",
htab, htab->filled, htab->size,

View File

@ -199,6 +199,6 @@ def test_efi_grub_net(u_boot_console):
# Then exit cleanly
u_boot_console.wait_for('grub>')
u_boot_console.run_command('exit', wait_for_prompt=False, wait_for_echo=False)
u_boot_console.wait_for('=>')
u_boot_console.wait_for(u_boot_console.prompt)
# And give us our U-Boot prompt back
u_boot_console.run_command('')

View File

@ -36,7 +36,7 @@ def test_efi_selftest_device_tree(u_boot_console):
output = u_boot_console.run_command('bootefi selftest')
assert '\'device tree\'' in output
u_boot_console.run_command(cmd='setenv efi_selftest device tree')
u_boot_console.run_command(cmd='setenv -f serial# Testing DT')
u_boot_console.run_command(cmd='setenv serial# Testing DT')
u_boot_console.run_command(cmd='bootefi selftest ${fdtcontroladdr}', wait_for_prompt=False)
m = u_boot_console.p.expect(['serial-number: Testing DT', 'U-Boot'])
if m != 0:

View File

@ -4,6 +4,10 @@
# Test operation of shell commands relating to environment variables.
import os
import os.path
from subprocess import call, check_call, CalledProcessError
import pytest
import u_boot_utils
@ -374,7 +378,6 @@ def test_env_info(state_test_env):
@pytest.mark.buildconfigspec('cmd_nvedit_info')
@pytest.mark.buildconfigspec('cmd_echo')
def test_env_info_sandbox(state_test_env):
"""Test 'env info' command result with several options on sandbox
with a known ENV configuration: ready & default & persistent
"""
@ -399,3 +402,111 @@ def test_env_info_sandbox(state_test_env):
response = c.run_command('env info -d -p -q')
response = c.run_command('echo $?')
assert response == "1"
def mk_env_ext4(state_test_env):
"""Create a empty ext4 file system volume."""
c = state_test_env.u_boot_console
filename = 'env.ext4.img'
persistent = c.config.persistent_data_dir + '/' + filename
fs_img = c.config.result_dir + '/' + filename
if os.path.exists(persistent):
c.log.action('Disk image file ' + persistent + ' already exists')
else:
try:
u_boot_utils.run_and_log(c, 'dd if=/dev/zero of=%s bs=1M count=16' % persistent)
u_boot_utils.run_and_log(c, 'mkfs.ext4 -O ^metadata_csum %s' % persistent)
except CalledProcessError:
call('rm -f %s' % persistent, shell=True)
raise
u_boot_utils.run_and_log(c, ['cp', '-f', persistent, fs_img])
return fs_img
@pytest.mark.boardspec('sandbox')
@pytest.mark.buildconfigspec('cmd_echo')
@pytest.mark.buildconfigspec('cmd_nvedit_info')
@pytest.mark.buildconfigspec('cmd_nvedit_load')
@pytest.mark.buildconfigspec('cmd_nvedit_select')
@pytest.mark.buildconfigspec('env_is_in_ext4')
def test_env_ext4(state_test_env):
"""Test ENV in EXT4 on sandbox."""
c = state_test_env.u_boot_console
fs_img = ''
try:
fs_img = mk_env_ext4(state_test_env)
c.run_command('host bind 0 %s' % fs_img)
response = c.run_command('ext4ls host 0:0')
assert 'uboot.env' not in response
# force env location: EXT4 (prio 1 in sandbox)
response = c.run_command('env select EXT4')
assert 'Select Environment on EXT4: OK' in response
response = c.run_command('env save')
assert 'Saving Environment to EXT4' in response
response = c.run_command('env load')
assert 'Loading Environment from EXT4... OK' in response
response = c.run_command('ext4ls host 0:0')
assert '8192 uboot.env' in response
response = c.run_command('env info')
assert 'env_valid = valid' in response
assert 'env_ready = true' in response
assert 'env_use_default = false' in response
response = c.run_command('env info -p -d')
assert 'Environment was loaded from persistent storage' in response
assert 'Environment can be persisted' in response
response = c.run_command('env info -d -q')
assert response == ""
response = c.run_command('echo $?')
assert response == "1"
response = c.run_command('env info -p -q')
assert response == ""
response = c.run_command('echo $?')
assert response == "0"
response = c.run_command('env erase')
assert 'OK' in response
response = c.run_command('env load')
assert 'Loading Environment from EXT4... ' in response
assert 'bad CRC, using default environment' in response
response = c.run_command('env info')
assert 'env_valid = invalid' in response
assert 'env_ready = true' in response
assert 'env_use_default = true' in response
response = c.run_command('env info -p -d')
assert 'Default environment is used' in response
assert 'Environment can be persisted' in response
# restore env location: NOWHERE (prio 0 in sandbox)
response = c.run_command('env select nowhere')
assert 'Select Environment on nowhere: OK' in response
response = c.run_command('env load')
assert 'Loading Environment from nowhere... OK' in response
response = c.run_command('env info')
assert 'env_valid = invalid' in response
assert 'env_ready = true' in response
assert 'env_use_default = true' in response
response = c.run_command('env info -p -d')
assert 'Default environment is used' in response
assert 'Environment cannot be persisted' in response
finally:
if fs_img:
call('rm -f %s' % fs_img, shell=True)

24
tools/env/fw_env.c vendored
View File

@ -995,6 +995,7 @@ static int flash_write_buf(int dev, int fd, void *buf, size_t count)
of the data */
loff_t blockstart; /* running start of the current block -
MEMGETBADBLOCK needs 64 bits */
int was_locked; /* flash lock flag */
int rc;
/*
@ -1080,6 +1081,12 @@ static int flash_write_buf(int dev, int fd, void *buf, size_t count)
}
erase.length = erasesize;
if (DEVTYPE(dev) != MTD_ABSENT) {
was_locked = ioctl(fd, MEMISLOCKED, &erase);
/* treat any errors as unlocked flash */
if (was_locked < 0)
was_locked = 0;
}
/* This only runs once on NOR flash and SPI-dataflash */
while (processed < write_total) {
@ -1099,7 +1106,8 @@ static int flash_write_buf(int dev, int fd, void *buf, size_t count)
if (DEVTYPE(dev) != MTD_ABSENT) {
erase.start = blockstart;
ioctl(fd, MEMUNLOCK, &erase);
if (was_locked)
ioctl(fd, MEMUNLOCK, &erase);
/* These do not need an explicit erase cycle */
if (DEVTYPE(dev) != MTD_DATAFLASH)
if (ioctl(fd, MEMERASE, &erase) != 0) {
@ -1127,8 +1135,10 @@ static int flash_write_buf(int dev, int fd, void *buf, size_t count)
return -1;
}
if (DEVTYPE(dev) != MTD_ABSENT)
ioctl(fd, MEMLOCK, &erase);
if (DEVTYPE(dev) != MTD_ABSENT) {
if (was_locked)
ioctl(fd, MEMLOCK, &erase);
}
processed += erasesize;
block_seek = 0;
@ -1149,7 +1159,9 @@ static int flash_flag_obsolete(int dev, int fd, off_t offset)
int rc;
struct erase_info_user erase;
char tmp = ENV_REDUND_OBSOLETE;
int was_locked; /* flash lock flag */
was_locked = ioctl(fd, MEMISLOCKED, &erase);
erase.start = DEVOFFSET(dev);
erase.length = DEVESIZE(dev);
/* This relies on the fact, that ENV_REDUND_OBSOLETE == 0 */
@ -1159,9 +1171,11 @@ static int flash_flag_obsolete(int dev, int fd, off_t offset)
DEVNAME(dev));
return rc;
}
ioctl(fd, MEMUNLOCK, &erase);
if (was_locked)
ioctl(fd, MEMUNLOCK, &erase);
rc = write(fd, &tmp, sizeof(tmp));
ioctl(fd, MEMLOCK, &erase);
if (was_locked)
ioctl(fd, MEMLOCK, &erase);
if (rc < 0)
perror("Could not set obsolete flag");