#define _GNU_SOURCE
#include <compiler.h>
+#include <env.h>
#include <errno.h>
#include <env_flags.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
+#include <u-boot/crc.h>
#include <unistd.h>
#include <dirent.h>
unsigned char *flags;
char *data;
enum flag_scheme flag_scheme;
+ int dirty;
};
static struct environment environment = {
static int have_redund_env;
-static unsigned char active_flag = 1;
-/* obsolete_flag must be 0 to efficiently set it on NOR flash without erasing */
-static unsigned char obsolete_flag = 0;
-
#define DEFAULT_ENV_INSTANCE_STATIC
#include <env_default.h>
if (!opts)
opts = &default_opts;
+ if (!environment.dirty)
+ return 0;
+
/*
* Update CRC
*/
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) {
/* Nothing to do */
return 0;
+ environment.dirty = 1;
if (deleting || overwriting) {
if (*++nxt == '\0') {
*env = '\0';
int fw_parse_script(char *fname, struct env_opts *opts)
{
FILE *fp;
- char dump[1024]; /* Maximum line length in the file */
+ char *line = NULL;
+ size_t linesize = 0;
char *name;
char *val;
int lineno = 0;
}
}
- while (fgets(dump, sizeof(dump), fp)) {
+ while ((len = getline(&line, &linesize, fp)) != -1) {
lineno++;
- len = strlen(dump);
/*
- * Read a whole line from the file. If the line is too long
- * or is not terminated, reports an error and exit.
+ * Read a whole line from the file. If the line is not
+ * terminated, reports an error and exit.
*/
- if (dump[len - 1] != '\n') {
+ if (line[len - 1] != '\n') {
fprintf(stderr,
- "Line %d not corrected terminated or too long\n",
+ "Line %d not correctly terminated\n",
lineno);
ret = -1;
break;
}
/* Drop ending line feed / carriage return */
- dump[--len] = '\0';
- if (len && dump[len - 1] == '\r')
- dump[--len] = '\0';
+ line[--len] = '\0';
+ if (len && line[len - 1] == '\r')
+ line[--len] = '\0';
/* Skip comment or empty lines */
- if (len == 0 || dump[0] == '#')
+ if (len == 0 || line[0] == '#')
continue;
/*
- * Search for variable's name,
- * remove leading whitespaces
+ * Search for variable's name remove leading whitespaces
*/
- name = skip_blanks(dump);
+ name = skip_blanks(line);
if (!name)
continue;
}
}
+ free(line);
/* Close file if not stdin */
if (strcmp(fname, "-") != 0)
}
/**
- * environment_end() - compute offset of first byte right after environemnt
+ * environment_end() - compute offset of first byte right after environment
* @dev - index of enviroment buffer
* Return:
- * device offset of first byte right after environemnt
+ * device offset of first byte right after environment
*/
off_t environment_end(int dev)
{
{
int rc;
struct erase_info_user erase;
+ char tmp = ENV_REDUND_OBSOLETE;
erase.start = DEVOFFSET(dev);
erase.length = DEVESIZE(dev);
- /* This relies on the fact, that obsolete_flag == 0 */
+ /* This relies on the fact, that ENV_REDUND_OBSOLETE == 0 */
rc = lseek(fd, offset, SEEK_SET);
if (rc < 0) {
fprintf(stderr, "Cannot seek to set the flag on %s\n",
return rc;
}
ioctl(fd, MEMUNLOCK, &erase);
- rc = write(fd, &obsolete_flag, sizeof(obsolete_flag));
+ rc = write(fd, &tmp, sizeof(tmp));
ioctl(fd, MEMLOCK, &erase);
if (rc < 0)
perror("Could not set obsolete flag");
(*environment.flags)++;
break;
case FLAG_BOOLEAN:
- *environment.flags = active_flag;
+ *environment.flags = ENV_REDUND_ACTIVE;
break;
default:
fprintf(stderr, "Unimplemented flash scheme %u\n",
rc = -1;
}
- if (target_temp) {
+ if (rc >= 0 && target_temp) {
int dir_fd;
dir_fd = open(dname, O_DIRECTORY | O_RDONLY);
"Warning: Bad CRC, using default environment\n");
memcpy(environment.data, default_environment,
sizeof(default_environment));
+ environment.dirty = 1;
}
} else {
flag0 = *environment.flags;
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) {
"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) {
case FLAG_BOOLEAN:
- if (flag0 == active_flag &&
- flag1 == obsolete_flag) {
+ if (flag0 == ENV_REDUND_ACTIVE &&
+ flag1 == ENV_REDUND_OBSOLETE) {
dev_current = 0;
- } else if (flag0 == obsolete_flag &&
- flag1 == active_flag) {
+ } else if (flag0 == ENV_REDUND_OBSOLETE &&
+ flag1 == ENV_REDUND_ACTIVE) {
dev_current = 1;
} else if (flag0 == flag1) {
dev_current = 0;
free(addr0);
if (addr1)
- free(addr0);
+ free(addr1);
return ret;
}
goto err;
}
DEVTYPE(dev) = mtdinfo.type;
+ if (DEVESIZE(dev) == 0 && ENVSECTORS(dev) == 0 &&
+ mtdinfo.type == MTD_NORFLASH)
+ DEVESIZE(dev) = mtdinfo.erasesize;
if (DEVESIZE(dev) == 0)
/* Assume the erase size is the same as the env-size */
DEVESIZE(dev) = ENVSIZE(dev);
if (ENVSIZE(0) != ENVSIZE(1)) {
fprintf(stderr,
- "Redundant environments have unequal size");
+ "Redundant environments have unequal size\n");
return -1;
}
}
FILE *fp;
int i = 0;
int rc;
- char dump[128];
+ char *line = NULL;
+ size_t linesize = 0;
char *devname;
fp = fopen(fname, "r");
if (fp == NULL)
return -1;
- while (i < 2 && fgets(dump, sizeof(dump), fp)) {
- /* Skip incomplete conversions and comment strings */
- if (dump[0] == '#')
+ while (i < 2 && getline(&line, &linesize, fp) != -1) {
+ /* Skip comment strings */
+ if (line[0] == '#')
continue;
- rc = sscanf(dump, "%ms %lli %lx %lx %lx",
+ rc = sscanf(line, "%ms %lli %lx %lx %lx",
&devname,
&DEVOFFSET(i),
&ENVSIZE(i), &DEVESIZE(i), &ENVSECTORS(i));
i++;
}
+ free(line);
fclose(fp);
have_redund_env = i - 1;