Skip to content

Commit

Permalink
fw_setenv: avoid writing environment when nothing has changed
Browse files Browse the repository at this point in the history
In the case where one deletes an already-non-existing variable, or sets
a variable to the value it already has, there is no point in writing the
environment back, thus reducing wear on the underlying storage
device.

In the case of redundant environments, if the two environments
differ (e.g. because one is corrupt), make sure that any call of
fw_setenv causes the two to become synchronized, even if the fw_setenv
call does not change anything in the good copy.

Signed-off-by: Rasmus Villemoes <[email protected]>
Acked-by: Joe Hershberger <[email protected]>
  • Loading branch information
Rasmus Villemoes authored and jhershbe committed Dec 20, 2019
1 parent 1785d8c commit c62e614
Showing 1 changed file with 19 additions and 1 deletion.
20 changes: 19 additions & 1 deletion tools/env/fw_env.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ struct environment {
unsigned char *flags;
char *data;
enum flag_scheme flag_scheme;
int dirty;
};

static struct environment environment = {
Expand Down Expand Up @@ -506,6 +507,9 @@ int fw_env_flush(struct env_opts *opts)
if (!opts)
opts = &default_opts;

if (!environment.dirty)
return 0;

/*
* Update CRC
*/
Expand Down Expand Up @@ -551,7 +555,8 @@ int fw_env_write(char *name, char *value)

deleting = (oldval && !(value && strlen(value)));
creating = (!oldval && (value && strlen(value)));
overwriting = (oldval && (value && strlen(value)));
overwriting = (oldval && (value && strlen(value) &&
strcmp(oldval, value)));

/* check for permission */
if (deleting) {
Expand Down Expand Up @@ -591,6 +596,7 @@ int fw_env_write(char *name, char *value)
/* Nothing to do */
return 0;

environment.dirty = 1;
if (deleting || overwriting) {
if (*++nxt == '\0') {
*env = '\0';
Expand Down Expand Up @@ -1440,6 +1446,7 @@ int fw_env_open(struct env_opts *opts)
"Warning: Bad CRC, using default environment\n");
memcpy(environment.data, default_environment,
sizeof(default_environment));
environment.dirty = 1;
}
} else {
flag0 = *environment.flags;
Expand Down Expand Up @@ -1493,6 +1500,16 @@ int fw_env_open(struct env_opts *opts)
crc1_ok = (crc1 == redundant->crc);
flag1 = redundant->flags;

/*
* environment.data still points to ((struct
* env_image_redundant *)addr0)->data. If the two
* environments differ, or one has bad crc, force a
* write-out by marking the environment dirty.
*/
if (memcmp(environment.data, redundant->data, ENV_SIZE) ||
!crc0_ok || !crc1_ok)
environment.dirty = 1;

if (crc0_ok && !crc1_ok) {
dev_current = 0;
} else if (!crc0_ok && crc1_ok) {
Expand All @@ -1502,6 +1519,7 @@ int fw_env_open(struct env_opts *opts)
"Warning: Bad CRC, using default environment\n");
memcpy(environment.data, default_environment,
sizeof(default_environment));
environment.dirty = 1;
dev_current = 0;
} else {
switch (environment.flag_scheme) {
Expand Down

0 comments on commit c62e614

Please sign in to comment.