summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2020-07-31 10:13:07 -0400
committerTom Rini <trini@konsulko.com>2020-07-31 10:13:07 -0400
commita2d051e7b6a8f87add1067d936bb0c805a47b0df (patch)
tree671af1a640f1fbb27f87a82685d8be9e632ee564
parent719f42190d5f0238cb01ef2ffba8af2285f7bc7a (diff)
parentdb82015929aeff6b58982a22d61ab8c5b87752f3 (diff)
downloadu-boot-WIP/31Jul2020.tar.gz
Merge branch '2020-07-31-more-env-updates'WIP/31Jul2020
- 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.
-rw-r--r--board/sandbox/sandbox.c15
-rw-r--r--cmd/Kconfig11
-rw-r--r--cmd/nvedit.c29
-rw-r--r--configs/sandbox64_defconfig7
-rw-r--r--configs/sandbox_defconfig7
-rw-r--r--configs/sandbox_flattree_defconfig7
-rw-r--r--configs/sandbox_spl_defconfig7
-rw-r--r--env/Kconfig19
-rw-r--r--env/common.c16
-rw-r--r--env/eeprom.c2
-rw-r--r--env/env.c82
-rw-r--r--env/ext4.c54
-rw-r--r--env/fat.c2
-rw-r--r--env/flags.c66
-rw-r--r--env/flash.c2
-rw-r--r--env/mmc.c4
-rw-r--r--env/nand.c4
-rw-r--r--env/nowhere.c17
-rw-r--r--env/nvram.c2
-rw-r--r--env/onenand.c2
-rw-r--r--env/remote.c2
-rw-r--r--env/sata.c2
-rw-r--r--env/sf.c6
-rw-r--r--env/ubi.c4
-rw-r--r--include/env.h22
-rw-r--r--include/env_flags.h6
-rw-r--r--include/env_internal.h23
-rw-r--r--include/search.h2
-rw-r--r--lib/hashtable.c9
-rw-r--r--test/py/tests/test_efi_loader.py2
-rw-r--r--test/py/tests/test_efi_selftest.py2
-rw-r--r--test/py/tests/test_env.py113
-rw-r--r--tools/env/fw_env.c24
33 files changed, 507 insertions, 65 deletions
diff --git a/board/sandbox/sandbox.c b/board/sandbox/sandbox.c
index c1317a8ca3..937ce28411 100644
--- a/board/sandbox/sandbox.c
+++ b/board/sandbox/sandbox.c
@@ -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;
diff --git a/cmd/Kconfig b/cmd/Kconfig
index bea2ddf830..d7136b0e79 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -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"
diff --git a/cmd/nvedit.c b/cmd/nvedit.c
index acd9f82667..d188c6aa6b 100644
--- a/cmd/nvedit.c
+++ b/cmd/nvedit.c
@@ -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)
@@ -1347,6 +1364,9 @@ static struct cmd_tbl cmd_env_sub[] = {
#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)
U_BOOT_CMD_MKENT(run, CONFIG_SYS_MAXARGS, 1, do_run, "", ""),
@@ -1357,6 +1377,9 @@ static struct cmd_tbl cmd_env_sub[] = {
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)
U_BOOT_CMD_MKENT(exists, 2, 0, do_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"
diff --git a/configs/sandbox64_defconfig b/configs/sandbox64_defconfig
index e8a1d57285..1228c49727 100644
--- a/configs/sandbox64_defconfig
+++ b/configs/sandbox64_defconfig
@@ -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
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 5bb44c780f..f4f97f34ff 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -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
diff --git a/configs/sandbox_flattree_defconfig b/configs/sandbox_flattree_defconfig
index 4b28b8e71c..78d732d0bc 100644
--- a/configs/sandbox_flattree_defconfig
+++ b/configs/sandbox_flattree_defconfig
@@ -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
diff --git a/configs/sandbox_spl_defconfig b/configs/sandbox_spl_defconfig
index 4549a81ff0..b846487f23 100644
--- a/configs/sandbox_spl_defconfig
+++ b/configs/sandbox_spl_defconfig
@@ -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
diff --git a/env/Kconfig b/env/Kconfig
index 4113628f49..5d0a8ecea0 100644
--- a/env/Kconfig
+++ b/env/Kconfig
@@ -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
diff --git a/env/common.c b/env/common.c
index 088b2aebb4..ed18378000 100644
--- a/env/common.c
+++ b/env/common.c
@@ -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 */
diff --git a/env/eeprom.c b/env/eeprom.c
index e8126cfe39..e300470ad0 100644
--- a/env/eeprom.c
+++ b/env/eeprom.c
@@ -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)
diff --git a/env/env.c b/env/env.c
index 2e64346438..42c7d8155e 100644
--- a/env/env.c
+++ b/env/env.c
@@ -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;
+}
diff --git a/env/ext4.c b/env/ext4.c
index 8e90bb71b7..f823b69409 100644
--- a/env/ext4.c
+++ b/env/ext4.c
@@ -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,
};
diff --git a/env/fat.c b/env/fat.c
index 63aced9317..71bf8bfa18 100644
--- a/env/fat.c
+++ b/env/fat.c
@@ -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);
diff --git a/env/flags.c b/env/flags.c
index b88fe7ba9c..df4aed26b2 100644
--- a/env/flags.c
+++ b/env/flags.c
@@ -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:
diff --git a/env/flash.c b/env/flash.c
index 3198147c38..722d5adf8b 100644
--- a/env/flash.c
+++ b/env/flash.c
@@ -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 */
diff --git a/env/mmc.c b/env/mmc.c
index aca61b75e9..af7e5fbac3 100644
--- a/env/mmc.c
+++ b/env/mmc.c
@@ -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;
diff --git a/env/nand.c b/env/nand.c
index 8b0027d304..0d7ee19bc2 100644
--- a/env/nand.c
+++ b/env/nand.c
@@ -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;
diff --git a/env/nowhere.c b/env/nowhere.c
index f5b0a17652..d33fdf27d0 100644
--- a/env/nowhere.c
+++ b/env/nowhere.c
@@ -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")
};
diff --git a/env/nvram.c b/env/nvram.c
index 1a9fcf1c06..7c8ea26f96 100644
--- a/env/nvram.c
+++ b/env/nvram.c
@@ -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)
diff --git a/env/onenand.c b/env/onenand.c
index dfd4e939f8..a2477cef9b 100644
--- a/env/onenand.c
+++ b/env/onenand.c
@@ -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;
diff --git a/env/remote.c b/env/remote.c
index e3f0608b16..d93a137376 100644
--- a/env/remote.c
+++ b/env/remote.c
@@ -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;
diff --git a/env/sata.c b/env/sata.c
index 8bfcc94306..9442cfcaf3 100644
--- a/env/sata.c
+++ b/env/sata.c
@@ -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) = {
diff --git a/env/sf.c b/env/sf.c
index 3e524f2947..937778aa37 100644
--- a/env/sf.c
+++ b/env/sf.c
@@ -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)
diff --git a/env/ubi.c b/env/ubi.c
index 08aac47df2..5502efe28b 100644
--- a/env/ubi.c
+++ b/env/ubi.c
@@ -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 */
diff --git a/include/env.h b/include/env.h
index d6c2d751d6..af405955b0 100644
--- a/include/env.h
+++ b/include/env.h
@@ -266,6 +266,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
*
* @return 0 if OK, -ve on error
@@ -280,6 +287,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
*
* This imports the environment from a buffer. The format for each variable is
@@ -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
diff --git a/include/env_flags.h b/include/env_flags.h
index 725841a891..313cb8c49a 100644
--- a/include/env_flags.h
+++ b/include/env_flags.h
@@ -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__ */
diff --git a/include/env_internal.h b/include/env_internal.h
index 66550434c3..b26dc6239c 100644
--- a/include/env_internal.h
+++ b/include/env_internal.h
@@ -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
*/
@@ -212,6 +211,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
*
* It is a weak function allowing board to overidde the environment location
diff --git a/include/search.h b/include/search.h
index bca36d3abc..e56843c26f 100644
--- a/include/search.h
+++ b/include/search.h
@@ -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_ */
diff --git a/lib/hashtable.c b/lib/hashtable.c
index 7b6781bc35..4a8c50b4b8 100644
--- a/lib/hashtable.c
+++ b/lib/hashtable.c
@@ -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,
diff --git a/test/py/tests/test_efi_loader.py b/test/py/tests/test_efi_loader.py
index ca68626cec..fc8d6b8655 100644
--- a/test/py/tests/test_efi_loader.py
+++ b/test/py/tests/test_efi_loader.py
@@ -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('')
diff --git a/test/py/tests/test_efi_selftest.py b/test/py/tests/test_efi_selftest.py
index 971c9f6053..9b520c2070 100644
--- a/test/py/tests/test_efi_selftest.py
+++ b/test/py/tests/test_efi_selftest.py
@@ -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:
diff --git a/test/py/tests/test_env.py b/test/py/tests/test_env.py
index a64aaa9bc5..86ec1b36d3 100644
--- a/test/py/tests/test_env.py
+++ b/test/py/tests/test_env.py
@@ -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)
diff --git a/tools/env/fw_env.c b/tools/env/fw_env.c
index c6378ecf34..3ab1ae69c7 100644
--- a/tools/env/fw_env.c
+++ b/tools/env/fw_env.c
@@ -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");