Newer
Older
if (HaveRedundEnv) {
/* switch to next partition for writing */
dev_target = !dev_current;
/* dev_target: fd_target, erase_target */
fd_target = open (DEVNAME (dev_target), mode);
if (fd_target < 0) {
fprintf (stderr,
"Can't open %s: %s\n",
DEVNAME (dev_target),
strerror (errno));
rc = -1;
goto exit;
} else {
dev_target = dev_current;
fd_target = fd_current;
rc = flash_write (fd_current, fd_target, dev_target);
if (HaveRedundEnv) {
fprintf (stderr,
}
} else {
fprintf (stderr,
"I/O error on %s: %s\n",
DEVNAME (dev_current), strerror (errno));
return -1;
}
/*
* s1 is either a simple 'name', or a 'name=value' pair.
* s2 is a 'name=value' pair.
* If the names match, return the value of s2, else NULL.
*/
static char *envmatch (char * s1, char * s2)
{
while (*s1 == *s2++)
if (*s1++ == '=')
if (*s1 == '\0' && *(s2 - 1) == '=')
}
/*
* Prevent confusion if running from erased flash memory
*/
int fw_env_open(void)
int crc0, crc0_ok;
char flag0;
void *addr0;
int crc1, crc1_ok;
struct env_image_single *single;
struct env_image_redundant *redundant;
if (parse_config ()) /* should fill envdevices */
addr0 = calloc (1, CONFIG_ENV_SIZE);
fprintf (stderr,
"Not enough memory for environment (%ld bytes)\n",
CONFIG_ENV_SIZE);
/* read environment from FLASH to local buffer */
environment.image = addr0;
if (HaveRedundEnv) {
redundant = addr0;
environment.crc = &redundant->crc;
environment.flags = &redundant->flags;
environment.data = redundant->data;
} else {
single = addr0;
environment.crc = &single->crc;
environment.flags = NULL;
environment.data = single->data;
dev_current = 0;
if (flash_io (O_RDONLY))
return -1;
crc0 = crc32 (0, (uint8_t *) environment.data, ENV_SIZE);
crc0_ok = (crc0 == *environment.crc);
if (!HaveRedundEnv) {
fprintf (stderr,
"Warning: Bad CRC, using default environment\n");
memcpy(environment.data, default_environment, sizeof default_environment);
addr1 = calloc (1, CONFIG_ENV_SIZE);
fprintf (stderr,
"Not enough memory for environment (%ld bytes)\n",
CONFIG_ENV_SIZE);
/*
* have to set environment.image for flash_read(), careful -
* other pointers in environment still point inside addr0
*/
environment.image = addr1;
if (flash_io (O_RDONLY))
return -1;
/* Check flag scheme compatibility */
if (DEVTYPE(dev_current) == MTD_NORFLASH &&
DEVTYPE(!dev_current) == MTD_NORFLASH) {
environment.flag_scheme = FLAG_BOOLEAN;
} else if (DEVTYPE(dev_current) == MTD_NANDFLASH &&
DEVTYPE(!dev_current) == MTD_NANDFLASH) {
environment.flag_scheme = FLAG_INCREMENTAL;
} else {
fprintf (stderr, "Incompatible flash types!\n");
return -1;
crc1 = crc32 (0, (uint8_t *) redundant->data, ENV_SIZE);
crc1_ok = (crc1 == redundant->crc);
flag1 = redundant->flags;
if (crc0_ok && !crc1_ok) {
dev_current = 0;
} else if (!crc0_ok && crc1_ok) {
dev_current = 1;
} else if (!crc0_ok && !crc1_ok) {
fprintf (stderr,
"Warning: Bad CRC, using default environment\n");
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
memcpy (environment.data, default_environment,
sizeof default_environment);
dev_current = 0;
} else {
switch (environment.flag_scheme) {
case FLAG_BOOLEAN:
if (flag0 == active_flag &&
flag1 == obsolete_flag) {
dev_current = 0;
} else if (flag0 == obsolete_flag &&
flag1 == active_flag) {
dev_current = 1;
} else if (flag0 == flag1) {
dev_current = 0;
} else if (flag0 == 0xFF) {
dev_current = 0;
} else if (flag1 == 0xFF) {
dev_current = 1;
} else {
dev_current = 0;
}
break;
case FLAG_INCREMENTAL:
if ((flag0 == 255 && flag1 == 0) ||
flag1 > flag0)
dev_current = 1;
else if ((flag1 == 255 && flag0 == 0) ||
flag0 > flag1)
dev_current = 0;
else /* flags are equal - almost impossible */
dev_current = 0;
break;
default:
fprintf (stderr, "Unknown flag scheme %u \n",
environment.flag_scheme);
return -1;
}
}
/*
* If we are reading, we don't need the flag and the CRC any
* more, if we are writing, we will re-calculate CRC and update
* flags before writing out
*/
if (dev_current) {
environment.image = addr1;
environment.crc = &redundant->crc;
environment.flags = &redundant->flags;
environment.data = redundant->data;
free (addr0);
} else {
environment.image = addr0;
/* Other pointers are already set */
{
struct stat st;
#if defined(CONFIG_FILE)
/* Fills in DEVNAME(), ENVSIZE(), DEVESIZE(). Or don't. */
fprintf (stderr,
"Cannot parse config file: %s\n", strerror (errno));
strcpy (DEVNAME (0), DEVICE1_NAME);
DEVOFFSET (0) = DEVICE1_OFFSET;
ENVSIZE (0) = ENV1_SIZE;
DEVESIZE (0) = DEVICE1_ESIZE;
#ifdef HAVE_REDUND
strcpy (DEVNAME (1), DEVICE2_NAME);
DEVOFFSET (1) = DEVICE2_OFFSET;
ENVSIZE (1) = ENV2_SIZE;
DEVESIZE (1) = DEVICE2_ESIZE;
HaveRedundEnv = 1;
if (stat (DEVNAME (0), &st)) {
fprintf (stderr,
"Cannot access MTD device %s: %s\n",
DEVNAME (0), strerror (errno));
if (HaveRedundEnv && stat (DEVNAME (1), &st)) {
fprintf (stderr,
"Cannot access MTD device %s: %s\n",
DEVNAME (1), strerror (errno));
return 0;
}
#if defined(CONFIG_FILE)
static int get_config (char *fname)
{
FILE *fp;
int i = 0;
int rc;
char dump[128];
fp = fopen (fname, "r");
if (fp == NULL)
return -1;
while (i < 2 && fgets (dump, sizeof (dump), fp)) {
/* Skip incomplete conversions and comment strings */
rc = sscanf (dump, "%s %lx %lx %lx %lx",
DEVNAME (i),
&DEVOFFSET (i),
&ENVSIZE (i),
&DEVESIZE (i),
&ENVSECTORS (i));
if (rc < 4)
continue;
if (rc < 5)
/* Default - 1 sector */
ENVSECTORS (i) = 1;
i++;
}
HaveRedundEnv = i - 1;
if (!i) { /* No valid entries found */
} else
return 0;
}
#endif