Home | History | Annotate | Download | only in env
      1 // SPDX-License-Identifier: GPL-2.0+
      2 /*
      3  * (C) Copyright 2000-2010
      4  * Wolfgang Denk, DENX Software Engineering, wd (at) denx.de.
      5  *
      6  * (C) Copyright 2008
      7  * Guennadi Liakhovetski, DENX Software Engineering, lg (at) denx.de.
      8  */
      9 
     10 #define _GNU_SOURCE
     11 
     12 #include <compiler.h>
     13 #include <errno.h>
     14 #include <env_flags.h>
     15 #include <fcntl.h>
     16 #include <libgen.h>
     17 #include <linux/fs.h>
     18 #include <linux/stringify.h>
     19 #include <ctype.h>
     20 #include <stdio.h>
     21 #include <stdlib.h>
     22 #include <stddef.h>
     23 #include <string.h>
     24 #include <sys/types.h>
     25 #include <sys/ioctl.h>
     26 #include <sys/stat.h>
     27 #include <unistd.h>
     28 #include <dirent.h>
     29 
     30 #ifdef MTD_OLD
     31 # include <stdint.h>
     32 # include <linux/mtd/mtd.h>
     33 #else
     34 # define  __user	/* nothing */
     35 # include <mtd/mtd-user.h>
     36 #endif
     37 
     38 #include <mtd/ubi-user.h>
     39 
     40 #include "fw_env_private.h"
     41 #include "fw_env.h"
     42 
     43 struct env_opts default_opts = {
     44 #ifdef CONFIG_FILE
     45 	.config_file = CONFIG_FILE
     46 #endif
     47 };
     48 
     49 #define DIV_ROUND_UP(n, d)	(((n) + (d) - 1) / (d))
     50 
     51 #define min(x, y) ({				\
     52 	typeof(x) _min1 = (x);			\
     53 	typeof(y) _min2 = (y);			\
     54 	(void) (&_min1 == &_min2);		\
     55 	_min1 < _min2 ? _min1 : _min2; })
     56 
     57 struct envdev_s {
     58 	const char *devname;		/* Device name */
     59 	long long devoff;		/* Device offset */
     60 	ulong env_size;			/* environment size */
     61 	ulong erase_size;		/* device erase size */
     62 	ulong env_sectors;		/* number of environment sectors */
     63 	uint8_t mtd_type;		/* type of the MTD device */
     64 	int is_ubi;			/* set if we use UBI volume */
     65 };
     66 
     67 static struct envdev_s envdevices[2] = {
     68 	{
     69 		.mtd_type = MTD_ABSENT,
     70 	}, {
     71 		.mtd_type = MTD_ABSENT,
     72 	},
     73 };
     74 
     75 static int dev_current;
     76 
     77 #define DEVNAME(i)    envdevices[(i)].devname
     78 #define DEVOFFSET(i)  envdevices[(i)].devoff
     79 #define ENVSIZE(i)    envdevices[(i)].env_size
     80 #define DEVESIZE(i)   envdevices[(i)].erase_size
     81 #define ENVSECTORS(i) envdevices[(i)].env_sectors
     82 #define DEVTYPE(i)    envdevices[(i)].mtd_type
     83 #define IS_UBI(i)     envdevices[(i)].is_ubi
     84 
     85 #define CUR_ENVSIZE ENVSIZE(dev_current)
     86 
     87 static unsigned long usable_envsize;
     88 #define ENV_SIZE      usable_envsize
     89 
     90 struct env_image_single {
     91 	uint32_t crc;		/* CRC32 over data bytes    */
     92 	char data[];
     93 };
     94 
     95 struct env_image_redundant {
     96 	uint32_t crc;		/* CRC32 over data bytes    */
     97 	unsigned char flags;	/* active or obsolete */
     98 	char data[];
     99 };
    100 
    101 enum flag_scheme {
    102 	FLAG_NONE,
    103 	FLAG_BOOLEAN,
    104 	FLAG_INCREMENTAL,
    105 };
    106 
    107 struct environment {
    108 	void *image;
    109 	uint32_t *crc;
    110 	unsigned char *flags;
    111 	char *data;
    112 	enum flag_scheme flag_scheme;
    113 };
    114 
    115 static struct environment environment = {
    116 	.flag_scheme = FLAG_NONE,
    117 };
    118 
    119 static int have_redund_env;
    120 
    121 static unsigned char active_flag = 1;
    122 /* obsolete_flag must be 0 to efficiently set it on NOR flash without erasing */
    123 static unsigned char obsolete_flag = 0;
    124 
    125 #define DEFAULT_ENV_INSTANCE_STATIC
    126 #include <env_default.h>
    127 
    128 #define UBI_DEV_START "/dev/ubi"
    129 #define UBI_SYSFS "/sys/class/ubi"
    130 #define UBI_VOL_NAME_PATT "ubi%d_%d"
    131 
    132 static int is_ubi_devname(const char *devname)
    133 {
    134 	return !strncmp(devname, UBI_DEV_START, sizeof(UBI_DEV_START) - 1);
    135 }
    136 
    137 static int ubi_check_volume_sysfs_name(const char *volume_sysfs_name,
    138 				       const char *volname)
    139 {
    140 	char path[256];
    141 	FILE *file;
    142 	char *name;
    143 	int ret;
    144 
    145 	strcpy(path, UBI_SYSFS "/");
    146 	strcat(path, volume_sysfs_name);
    147 	strcat(path, "/name");
    148 
    149 	file = fopen(path, "r");
    150 	if (!file)
    151 		return -1;
    152 
    153 	ret = fscanf(file, "%ms", &name);
    154 	fclose(file);
    155 	if (ret <= 0 || !name) {
    156 		fprintf(stderr,
    157 			"Failed to read from file %s, ret = %d, name = %s\n",
    158 			path, ret, name);
    159 		return -1;
    160 	}
    161 
    162 	if (!strcmp(name, volname)) {
    163 		free(name);
    164 		return 0;
    165 	}
    166 	free(name);
    167 
    168 	return -1;
    169 }
    170 
    171 static int ubi_get_volnum_by_name(int devnum, const char *volname)
    172 {
    173 	DIR *sysfs_ubi;
    174 	struct dirent *dirent;
    175 	int ret;
    176 	int tmp_devnum;
    177 	int volnum;
    178 
    179 	sysfs_ubi = opendir(UBI_SYSFS);
    180 	if (!sysfs_ubi)
    181 		return -1;
    182 
    183 #ifdef DEBUG
    184 	fprintf(stderr, "Looking for volume name \"%s\"\n", volname);
    185 #endif
    186 
    187 	while (1) {
    188 		dirent = readdir(sysfs_ubi);
    189 		if (!dirent)
    190 			return -1;
    191 
    192 		ret = sscanf(dirent->d_name, UBI_VOL_NAME_PATT,
    193 			     &tmp_devnum, &volnum);
    194 		if (ret == 2 && devnum == tmp_devnum) {
    195 			if (ubi_check_volume_sysfs_name(dirent->d_name,
    196 							volname) == 0)
    197 				return volnum;
    198 		}
    199 	}
    200 
    201 	return -1;
    202 }
    203 
    204 static int ubi_get_devnum_by_devname(const char *devname)
    205 {
    206 	int devnum;
    207 	int ret;
    208 
    209 	ret = sscanf(devname + sizeof(UBI_DEV_START) - 1, "%d", &devnum);
    210 	if (ret != 1)
    211 		return -1;
    212 
    213 	return devnum;
    214 }
    215 
    216 static const char *ubi_get_volume_devname(const char *devname,
    217 					  const char *volname)
    218 {
    219 	char *volume_devname;
    220 	int volnum;
    221 	int devnum;
    222 	int ret;
    223 
    224 	devnum = ubi_get_devnum_by_devname(devname);
    225 	if (devnum < 0)
    226 		return NULL;
    227 
    228 	volnum = ubi_get_volnum_by_name(devnum, volname);
    229 	if (volnum < 0)
    230 		return NULL;
    231 
    232 	ret = asprintf(&volume_devname, "%s_%d", devname, volnum);
    233 	if (ret < 0)
    234 		return NULL;
    235 
    236 #ifdef DEBUG
    237 	fprintf(stderr, "Found ubi volume \"%s:%s\" -> %s\n",
    238 		devname, volname, volume_devname);
    239 #endif
    240 
    241 	return volume_devname;
    242 }
    243 
    244 static void ubi_check_dev(unsigned int dev_id)
    245 {
    246 	char *devname = (char *)DEVNAME(dev_id);
    247 	char *pname;
    248 	const char *volname = NULL;
    249 	const char *volume_devname;
    250 
    251 	if (!is_ubi_devname(DEVNAME(dev_id)))
    252 		return;
    253 
    254 	IS_UBI(dev_id) = 1;
    255 
    256 	for (pname = devname; *pname != '\0'; pname++) {
    257 		if (*pname == ':') {
    258 			*pname = '\0';
    259 			volname = pname + 1;
    260 			break;
    261 		}
    262 	}
    263 
    264 	if (volname) {
    265 		/* Let's find real volume device name */
    266 		volume_devname = ubi_get_volume_devname(devname, volname);
    267 		if (!volume_devname) {
    268 			fprintf(stderr, "Didn't found ubi volume \"%s\"\n",
    269 				volname);
    270 			return;
    271 		}
    272 
    273 		free(devname);
    274 		DEVNAME(dev_id) = volume_devname;
    275 	}
    276 }
    277 
    278 static int ubi_update_start(int fd, int64_t bytes)
    279 {
    280 	if (ioctl(fd, UBI_IOCVOLUP, &bytes))
    281 		return -1;
    282 	return 0;
    283 }
    284 
    285 static int ubi_read(int fd, void *buf, size_t count)
    286 {
    287 	ssize_t ret;
    288 
    289 	while (count > 0) {
    290 		ret = read(fd, buf, count);
    291 		if (ret > 0) {
    292 			count -= ret;
    293 			buf += ret;
    294 
    295 			continue;
    296 		}
    297 
    298 		if (ret == 0) {
    299 			/*
    300 			 * Happens in case of too short volume data size. If we
    301 			 * return error status we will fail it will be treated
    302 			 * as UBI device error.
    303 			 *
    304 			 * Leave catching this error to CRC check.
    305 			 */
    306 			fprintf(stderr, "Warning: end of data on ubi volume\n");
    307 			return 0;
    308 		} else if (errno == EBADF) {
    309 			/*
    310 			 * Happens in case of corrupted volume. The same as
    311 			 * above, we cannot return error now, as we will still
    312 			 * be able to successfully write environment later.
    313 			 */
    314 			fprintf(stderr, "Warning: corrupted volume?\n");
    315 			return 0;
    316 		} else if (errno == EINTR) {
    317 			continue;
    318 		}
    319 
    320 		fprintf(stderr, "Cannot read %u bytes from ubi volume, %s\n",
    321 			(unsigned int)count, strerror(errno));
    322 		return -1;
    323 	}
    324 
    325 	return 0;
    326 }
    327 
    328 static int ubi_write(int fd, const void *buf, size_t count)
    329 {
    330 	ssize_t ret;
    331 
    332 	while (count > 0) {
    333 		ret = write(fd, buf, count);
    334 		if (ret <= 0) {
    335 			if (ret < 0 && errno == EINTR)
    336 				continue;
    337 
    338 			fprintf(stderr, "Cannot write %u bytes to ubi volume\n",
    339 				(unsigned int)count);
    340 			return -1;
    341 		}
    342 
    343 		count -= ret;
    344 		buf += ret;
    345 	}
    346 
    347 	return 0;
    348 }
    349 
    350 static int flash_io(int mode);
    351 static int parse_config(struct env_opts *opts);
    352 
    353 #if defined(CONFIG_FILE)
    354 static int get_config(char *);
    355 #endif
    356 
    357 static char *skip_chars(char *s)
    358 {
    359 	for (; *s != '\0'; s++) {
    360 		if (isblank(*s) || *s == '=')
    361 			return s;
    362 	}
    363 	return NULL;
    364 }
    365 
    366 static char *skip_blanks(char *s)
    367 {
    368 	for (; *s != '\0'; s++) {
    369 		if (!isblank(*s))
    370 			return s;
    371 	}
    372 	return NULL;
    373 }
    374 
    375 /*
    376  * s1 is either a simple 'name', or a 'name=value' pair.
    377  * s2 is a 'name=value' pair.
    378  * If the names match, return the value of s2, else NULL.
    379  */
    380 static char *envmatch(char *s1, char *s2)
    381 {
    382 	if (s1 == NULL || s2 == NULL)
    383 		return NULL;
    384 
    385 	while (*s1 == *s2++)
    386 		if (*s1++ == '=')
    387 			return s2;
    388 	if (*s1 == '\0' && *(s2 - 1) == '=')
    389 		return s2;
    390 	return NULL;
    391 }
    392 
    393 /**
    394  * Search the environment for a variable.
    395  * Return the value, if found, or NULL, if not found.
    396  */
    397 char *fw_getenv(char *name)
    398 {
    399 	char *env, *nxt;
    400 
    401 	for (env = environment.data; *env; env = nxt + 1) {
    402 		char *val;
    403 
    404 		for (nxt = env; *nxt; ++nxt) {
    405 			if (nxt >= &environment.data[ENV_SIZE]) {
    406 				fprintf(stderr, "## Error: "
    407 					"environment not terminated\n");
    408 				return NULL;
    409 			}
    410 		}
    411 		val = envmatch(name, env);
    412 		if (!val)
    413 			continue;
    414 		return val;
    415 	}
    416 	return NULL;
    417 }
    418 
    419 /*
    420  * Search the default environment for a variable.
    421  * Return the value, if found, or NULL, if not found.
    422  */
    423 char *fw_getdefenv(char *name)
    424 {
    425 	char *env, *nxt;
    426 
    427 	for (env = default_environment; *env; env = nxt + 1) {
    428 		char *val;
    429 
    430 		for (nxt = env; *nxt; ++nxt) {
    431 			if (nxt >= &default_environment[ENV_SIZE]) {
    432 				fprintf(stderr, "## Error: "
    433 					"default environment not terminated\n");
    434 				return NULL;
    435 			}
    436 		}
    437 		val = envmatch(name, env);
    438 		if (!val)
    439 			continue;
    440 		return val;
    441 	}
    442 	return NULL;
    443 }
    444 
    445 /*
    446  * Print the current definition of one, or more, or all
    447  * environment variables
    448  */
    449 int fw_printenv(int argc, char *argv[], int value_only, struct env_opts *opts)
    450 {
    451 	int i, rc = 0;
    452 
    453 	if (value_only && argc != 1) {
    454 		fprintf(stderr,
    455 			"## Error: `-n'/`--noheader' option requires exactly one argument\n");
    456 		return -1;
    457 	}
    458 
    459 	if (!opts)
    460 		opts = &default_opts;
    461 
    462 	if (fw_env_open(opts))
    463 		return -1;
    464 
    465 	if (argc == 0) {	/* Print all env variables  */
    466 		char *env, *nxt;
    467 		for (env = environment.data; *env; env = nxt + 1) {
    468 			for (nxt = env; *nxt; ++nxt) {
    469 				if (nxt >= &environment.data[ENV_SIZE]) {
    470 					fprintf(stderr, "## Error: "
    471 						"environment not terminated\n");
    472 					return -1;
    473 				}
    474 			}
    475 
    476 			printf("%s\n", env);
    477 		}
    478 		fw_env_close(opts);
    479 		return 0;
    480 	}
    481 
    482 	for (i = 0; i < argc; ++i) {	/* print a subset of env variables */
    483 		char *name = argv[i];
    484 		char *val = NULL;
    485 
    486 		val = fw_getenv(name);
    487 		if (!val) {
    488 			fprintf(stderr, "## Error: \"%s\" not defined\n", name);
    489 			rc = -1;
    490 			continue;
    491 		}
    492 
    493 		if (value_only) {
    494 			puts(val);
    495 			break;
    496 		}
    497 
    498 		printf("%s=%s\n", name, val);
    499 	}
    500 
    501 	fw_env_close(opts);
    502 
    503 	return rc;
    504 }
    505 
    506 int fw_env_flush(struct env_opts *opts)
    507 {
    508 	if (!opts)
    509 		opts = &default_opts;
    510 
    511 	/*
    512 	 * Update CRC
    513 	 */
    514 	*environment.crc = crc32(0, (uint8_t *) environment.data, ENV_SIZE);
    515 
    516 	/* write environment back to flash */
    517 	if (flash_io(O_RDWR)) {
    518 		fprintf(stderr, "Error: can't write fw_env to flash\n");
    519 		return -1;
    520 	}
    521 
    522 	return 0;
    523 }
    524 
    525 /*
    526  * Set/Clear a single variable in the environment.
    527  * This is called in sequence to update the environment
    528  * in RAM without updating the copy in flash after each set
    529  */
    530 int fw_env_write(char *name, char *value)
    531 {
    532 	int len;
    533 	char *env, *nxt;
    534 	char *oldval = NULL;
    535 	int deleting, creating, overwriting;
    536 
    537 	/*
    538 	 * search if variable with this name already exists
    539 	 */
    540 	for (nxt = env = environment.data; *env; env = nxt + 1) {
    541 		for (nxt = env; *nxt; ++nxt) {
    542 			if (nxt >= &environment.data[ENV_SIZE]) {
    543 				fprintf(stderr, "## Error: "
    544 					"environment not terminated\n");
    545 				errno = EINVAL;
    546 				return -1;
    547 			}
    548 		}
    549 		oldval = envmatch(name, env);
    550 		if (oldval)
    551 			break;
    552 	}
    553 
    554 	deleting = (oldval && !(value && strlen(value)));
    555 	creating = (!oldval && (value && strlen(value)));
    556 	overwriting = (oldval && (value && strlen(value)));
    557 
    558 	/* check for permission */
    559 	if (deleting) {
    560 		if (env_flags_validate_varaccess(name,
    561 		    ENV_FLAGS_VARACCESS_PREVENT_DELETE)) {
    562 			printf("Can't delete \"%s\"\n", name);
    563 			errno = EROFS;
    564 			return -1;
    565 		}
    566 	} else if (overwriting) {
    567 		if (env_flags_validate_varaccess(name,
    568 		    ENV_FLAGS_VARACCESS_PREVENT_OVERWR)) {
    569 			printf("Can't overwrite \"%s\"\n", name);
    570 			errno = EROFS;
    571 			return -1;
    572 		} else if (env_flags_validate_varaccess(name,
    573 			   ENV_FLAGS_VARACCESS_PREVENT_NONDEF_OVERWR)) {
    574 			const char *defval = fw_getdefenv(name);
    575 
    576 			if (defval == NULL)
    577 				defval = "";
    578 			if (strcmp(oldval, defval)
    579 			    != 0) {
    580 				printf("Can't overwrite \"%s\"\n", name);
    581 				errno = EROFS;
    582 				return -1;
    583 			}
    584 		}
    585 	} else if (creating) {
    586 		if (env_flags_validate_varaccess(name,
    587 		    ENV_FLAGS_VARACCESS_PREVENT_CREATE)) {
    588 			printf("Can't create \"%s\"\n", name);
    589 			errno = EROFS;
    590 			return -1;
    591 		}
    592 	} else
    593 		/* Nothing to do */
    594 		return 0;
    595 
    596 	if (deleting || overwriting) {
    597 		if (*++nxt == '\0') {
    598 			*env = '\0';
    599 		} else {
    600 			for (;;) {
    601 				*env = *nxt++;
    602 				if ((*env == '\0') && (*nxt == '\0'))
    603 					break;
    604 				++env;
    605 			}
    606 		}
    607 		*++env = '\0';
    608 	}
    609 
    610 	/* Delete only ? */
    611 	if (!value || !strlen(value))
    612 		return 0;
    613 
    614 	/*
    615 	 * Append new definition at the end
    616 	 */
    617 	for (env = environment.data; *env || *(env + 1); ++env)
    618 		;
    619 	if (env > environment.data)
    620 		++env;
    621 	/*
    622 	 * Overflow when:
    623 	 * "name" + "=" + "val" +"\0\0"  > CUR_ENVSIZE - (env-environment)
    624 	 */
    625 	len = strlen(name) + 2;
    626 	/* add '=' for first arg, ' ' for all others */
    627 	len += strlen(value) + 1;
    628 
    629 	if (len > (&environment.data[ENV_SIZE] - env)) {
    630 		fprintf(stderr,
    631 			"Error: environment overflow, \"%s\" deleted\n", name);
    632 		return -1;
    633 	}
    634 
    635 	while ((*env = *name++) != '\0')
    636 		env++;
    637 	*env = '=';
    638 	while ((*++env = *value++) != '\0')
    639 		;
    640 
    641 	/* end is marked with double '\0' */
    642 	*++env = '\0';
    643 
    644 	return 0;
    645 }
    646 
    647 /*
    648  * Deletes or sets environment variables. Returns -1 and sets errno error codes:
    649  * 0	  - OK
    650  * EINVAL - need at least 1 argument
    651  * EROFS  - certain variables ("ethaddr", "serial#") cannot be
    652  *	    modified or deleted
    653  *
    654  */
    655 int fw_env_set(int argc, char *argv[], struct env_opts *opts)
    656 {
    657 	int i;
    658 	size_t len;
    659 	char *name, **valv;
    660 	char *oldval;
    661 	char *value = NULL;
    662 	int valc;
    663 	int ret;
    664 
    665 	if (!opts)
    666 		opts = &default_opts;
    667 
    668 	if (argc < 1) {
    669 		fprintf(stderr, "## Error: variable name missing\n");
    670 		errno = EINVAL;
    671 		return -1;
    672 	}
    673 
    674 	if (fw_env_open(opts)) {
    675 		fprintf(stderr, "Error: environment not initialized\n");
    676 		return -1;
    677 	}
    678 
    679 	name = argv[0];
    680 	valv = argv + 1;
    681 	valc = argc - 1;
    682 
    683 	if (env_flags_validate_env_set_params(name, valv, valc) < 0) {
    684 		fw_env_close(opts);
    685 		return -1;
    686 	}
    687 
    688 	len = 0;
    689 	for (i = 0; i < valc; ++i) {
    690 		char *val = valv[i];
    691 		size_t val_len = strlen(val);
    692 
    693 		if (value)
    694 			value[len - 1] = ' ';
    695 		oldval = value;
    696 		value = realloc(value, len + val_len + 1);
    697 		if (!value) {
    698 			fprintf(stderr,
    699 				"Cannot malloc %zu bytes: %s\n",
    700 				len, strerror(errno));
    701 			free(oldval);
    702 			return -1;
    703 		}
    704 
    705 		memcpy(value + len, val, val_len);
    706 		len += val_len;
    707 		value[len++] = '\0';
    708 	}
    709 
    710 	fw_env_write(name, value);
    711 
    712 	free(value);
    713 
    714 	ret = fw_env_flush(opts);
    715 	fw_env_close(opts);
    716 
    717 	return ret;
    718 }
    719 
    720 /*
    721  * Parse  a file  and configure the u-boot variables.
    722  * The script file has a very simple format, as follows:
    723  *
    724  * Each line has a couple with name, value:
    725  * <white spaces>variable_name<white spaces>variable_value
    726  *
    727  * Both variable_name and variable_value are interpreted as strings.
    728  * Any character after <white spaces> and before ending \r\n is interpreted
    729  * as variable's value (no comment allowed on these lines !)
    730  *
    731  * Comments are allowed if the first character in the line is #
    732  *
    733  * Returns -1 and sets errno error codes:
    734  * 0	  - OK
    735  * -1     - Error
    736  */
    737 int fw_parse_script(char *fname, struct env_opts *opts)
    738 {
    739 	FILE *fp;
    740 	char *line = NULL;
    741 	size_t linesize = 0;
    742 	char *name;
    743 	char *val;
    744 	int lineno = 0;
    745 	int len;
    746 	int ret = 0;
    747 
    748 	if (!opts)
    749 		opts = &default_opts;
    750 
    751 	if (fw_env_open(opts)) {
    752 		fprintf(stderr, "Error: environment not initialized\n");
    753 		return -1;
    754 	}
    755 
    756 	if (strcmp(fname, "-") == 0)
    757 		fp = stdin;
    758 	else {
    759 		fp = fopen(fname, "r");
    760 		if (fp == NULL) {
    761 			fprintf(stderr, "I cannot open %s for reading\n",
    762 				fname);
    763 			return -1;
    764 		}
    765 	}
    766 
    767 	while ((len = getline(&line, &linesize, fp)) != -1) {
    768 		lineno++;
    769 
    770 		/*
    771 		 * Read a whole line from the file. If the line is not
    772 		 * terminated, reports an error and exit.
    773 		 */
    774 		if (line[len - 1] != '\n') {
    775 			fprintf(stderr,
    776 				"Line %d not correctly terminated\n",
    777 				lineno);
    778 			ret = -1;
    779 			break;
    780 		}
    781 
    782 		/* Drop ending line feed / carriage return */
    783 		line[--len] = '\0';
    784 		if (len && line[len - 1] == '\r')
    785 			line[--len] = '\0';
    786 
    787 		/* Skip comment or empty lines */
    788 		if (len == 0 || line[0] == '#')
    789 			continue;
    790 
    791 		/*
    792 		 * Search for variable's name remove leading whitespaces
    793 		 */
    794 		name = skip_blanks(line);
    795 		if (!name)
    796 			continue;
    797 
    798 		/* The first white space is the end of variable name */
    799 		val = skip_chars(name);
    800 		len = strlen(name);
    801 		if (val) {
    802 			*val++ = '\0';
    803 			if ((val - name) < len)
    804 				val = skip_blanks(val);
    805 			else
    806 				val = NULL;
    807 		}
    808 #ifdef DEBUG
    809 		fprintf(stderr, "Setting %s : %s\n",
    810 			name, val ? val : " removed");
    811 #endif
    812 
    813 		if (env_flags_validate_type(name, val) < 0) {
    814 			ret = -1;
    815 			break;
    816 		}
    817 
    818 		/*
    819 		 * If there is an error setting a variable,
    820 		 * try to save the environment and returns an error
    821 		 */
    822 		if (fw_env_write(name, val)) {
    823 			fprintf(stderr,
    824 				"fw_env_write returns with error : %s\n",
    825 				strerror(errno));
    826 			ret = -1;
    827 			break;
    828 		}
    829 
    830 	}
    831 	free(line);
    832 
    833 	/* Close file if not stdin */
    834 	if (strcmp(fname, "-") != 0)
    835 		fclose(fp);
    836 
    837 	ret |= fw_env_flush(opts);
    838 
    839 	fw_env_close(opts);
    840 
    841 	return ret;
    842 }
    843 
    844 /**
    845  * environment_end() - compute offset of first byte right after environment
    846  * @dev - index of enviroment buffer
    847  * Return:
    848  *  device offset of first byte right after environment
    849  */
    850 off_t environment_end(int dev)
    851 {
    852 	/* environment is block aligned */
    853 	return DEVOFFSET(dev) + ENVSECTORS(dev) * DEVESIZE(dev);
    854 }
    855 
    856 /*
    857  * Test for bad block on NAND, just returns 0 on NOR, on NAND:
    858  * 0	- block is good
    859  * > 0	- block is bad
    860  * < 0	- failed to test
    861  */
    862 static int flash_bad_block(int fd, uint8_t mtd_type, loff_t blockstart)
    863 {
    864 	if (mtd_type == MTD_NANDFLASH) {
    865 		int badblock = ioctl(fd, MEMGETBADBLOCK, &blockstart);
    866 
    867 		if (badblock < 0) {
    868 			perror("Cannot read bad block mark");
    869 			return badblock;
    870 		}
    871 
    872 		if (badblock) {
    873 #ifdef DEBUG
    874 			fprintf(stderr, "Bad block at 0x%llx, skipping\n",
    875 				(unsigned long long)blockstart);
    876 #endif
    877 			return badblock;
    878 		}
    879 	}
    880 
    881 	return 0;
    882 }
    883 
    884 /*
    885  * Read data from flash at an offset into a provided buffer. On NAND it skips
    886  * bad blocks but makes sure it stays within ENVSECTORS (dev) starting from
    887  * the DEVOFFSET (dev) block. On NOR the loop is only run once.
    888  */
    889 static int flash_read_buf(int dev, int fd, void *buf, size_t count,
    890 			  off_t offset)
    891 {
    892 	size_t blocklen;	/* erase / write length - one block on NAND,
    893 				   0 on NOR */
    894 	size_t processed = 0;	/* progress counter */
    895 	size_t readlen = count;	/* current read length */
    896 	off_t block_seek;	/* offset inside the current block to the start
    897 				   of the data */
    898 	loff_t blockstart;	/* running start of the current block -
    899 				   MEMGETBADBLOCK needs 64 bits */
    900 	int rc;
    901 
    902 	blockstart = (offset / DEVESIZE(dev)) * DEVESIZE(dev);
    903 
    904 	/* Offset inside a block */
    905 	block_seek = offset - blockstart;
    906 
    907 	if (DEVTYPE(dev) == MTD_NANDFLASH) {
    908 		/*
    909 		 * NAND: calculate which blocks we are reading. We have
    910 		 * to read one block at a time to skip bad blocks.
    911 		 */
    912 		blocklen = DEVESIZE(dev);
    913 
    914 		/* Limit to one block for the first read */
    915 		if (readlen > blocklen - block_seek)
    916 			readlen = blocklen - block_seek;
    917 	} else {
    918 		blocklen = 0;
    919 	}
    920 
    921 	/* This only runs once on NOR flash */
    922 	while (processed < count) {
    923 		rc = flash_bad_block(fd, DEVTYPE(dev), blockstart);
    924 		if (rc < 0)	/* block test failed */
    925 			return -1;
    926 
    927 		if (blockstart + block_seek + readlen > environment_end(dev)) {
    928 			/* End of range is reached */
    929 			fprintf(stderr, "Too few good blocks within range\n");
    930 			return -1;
    931 		}
    932 
    933 		if (rc) {	/* block is bad */
    934 			blockstart += blocklen;
    935 			continue;
    936 		}
    937 
    938 		/*
    939 		 * If a block is bad, we retry in the next block at the same
    940 		 * offset - see env/nand.c::writeenv()
    941 		 */
    942 		lseek(fd, blockstart + block_seek, SEEK_SET);
    943 
    944 		rc = read(fd, buf + processed, readlen);
    945 		if (rc != readlen) {
    946 			fprintf(stderr, "Read error on %s: %s\n",
    947 				DEVNAME(dev), strerror(errno));
    948 			return -1;
    949 		}
    950 #ifdef DEBUG
    951 		fprintf(stderr, "Read 0x%x bytes at 0x%llx on %s\n",
    952 			rc, (unsigned long long)blockstart + block_seek,
    953 			DEVNAME(dev));
    954 #endif
    955 		processed += readlen;
    956 		readlen = min(blocklen, count - processed);
    957 		block_seek = 0;
    958 		blockstart += blocklen;
    959 	}
    960 
    961 	return processed;
    962 }
    963 
    964 /*
    965  * Write count bytes from begin of environment, but stay within
    966  * ENVSECTORS(dev) sectors of
    967  * DEVOFFSET (dev). Similar to the read case above, on NOR and dataflash we
    968  * erase and write the whole data at once.
    969  */
    970 static int flash_write_buf(int dev, int fd, void *buf, size_t count)
    971 {
    972 	void *data;
    973 	struct erase_info_user erase;
    974 	size_t blocklen;	/* length of NAND block / NOR erase sector */
    975 	size_t erase_len;	/* whole area that can be erased - may include
    976 				   bad blocks */
    977 	size_t erasesize;	/* erase / write length - one block on NAND,
    978 				   whole area on NOR */
    979 	size_t processed = 0;	/* progress counter */
    980 	size_t write_total;	/* total size to actually write - excluding
    981 				   bad blocks */
    982 	off_t erase_offset;	/* offset to the first erase block (aligned)
    983 				   below offset */
    984 	off_t block_seek;	/* offset inside the erase block to the start
    985 				   of the data */
    986 	loff_t blockstart;	/* running start of the current block -
    987 				   MEMGETBADBLOCK needs 64 bits */
    988 	int rc;
    989 
    990 	/*
    991 	 * For mtd devices only offset and size of the environment do matter
    992 	 */
    993 	if (DEVTYPE(dev) == MTD_ABSENT) {
    994 		blocklen = count;
    995 		erase_len = blocklen;
    996 		blockstart = DEVOFFSET(dev);
    997 		block_seek = 0;
    998 		write_total = blocklen;
    999 	} else {
   1000 		blocklen = DEVESIZE(dev);
   1001 
   1002 		erase_offset = DEVOFFSET(dev);
   1003 
   1004 		/* Maximum area we may use */
   1005 		erase_len = environment_end(dev) - erase_offset;
   1006 
   1007 		blockstart = erase_offset;
   1008 
   1009 		/* Offset inside a block */
   1010 		block_seek = DEVOFFSET(dev) - erase_offset;
   1011 
   1012 		/*
   1013 		 * Data size we actually write: from the start of the block
   1014 		 * to the start of the data, then count bytes of data, and
   1015 		 * to the end of the block
   1016 		 */
   1017 		write_total = ((block_seek + count + blocklen - 1) /
   1018 			       blocklen) * blocklen;
   1019 	}
   1020 
   1021 	/*
   1022 	 * Support data anywhere within erase sectors: read out the complete
   1023 	 * area to be erased, replace the environment image, write the whole
   1024 	 * block back again.
   1025 	 */
   1026 	if (write_total > count) {
   1027 		data = malloc(erase_len);
   1028 		if (!data) {
   1029 			fprintf(stderr,
   1030 				"Cannot malloc %zu bytes: %s\n",
   1031 				erase_len, strerror(errno));
   1032 			return -1;
   1033 		}
   1034 
   1035 		rc = flash_read_buf(dev, fd, data, write_total, erase_offset);
   1036 		if (write_total != rc)
   1037 			return -1;
   1038 
   1039 #ifdef DEBUG
   1040 		fprintf(stderr, "Preserving data ");
   1041 		if (block_seek != 0)
   1042 			fprintf(stderr, "0x%x - 0x%lx", 0, block_seek - 1);
   1043 		if (block_seek + count != write_total) {
   1044 			if (block_seek != 0)
   1045 				fprintf(stderr, " and ");
   1046 			fprintf(stderr, "0x%lx - 0x%lx",
   1047 				(unsigned long)block_seek + count,
   1048 				(unsigned long)write_total - 1);
   1049 		}
   1050 		fprintf(stderr, "\n");
   1051 #endif
   1052 		/* Overwrite the old environment */
   1053 		memcpy(data + block_seek, buf, count);
   1054 	} else {
   1055 		/*
   1056 		 * We get here, iff offset is block-aligned and count is a
   1057 		 * multiple of blocklen - see write_total calculation above
   1058 		 */
   1059 		data = buf;
   1060 	}
   1061 
   1062 	if (DEVTYPE(dev) == MTD_NANDFLASH) {
   1063 		/*
   1064 		 * NAND: calculate which blocks we are writing. We have
   1065 		 * to write one block at a time to skip bad blocks.
   1066 		 */
   1067 		erasesize = blocklen;
   1068 	} else {
   1069 		erasesize = erase_len;
   1070 	}
   1071 
   1072 	erase.length = erasesize;
   1073 
   1074 	/* This only runs once on NOR flash and SPI-dataflash */
   1075 	while (processed < write_total) {
   1076 		rc = flash_bad_block(fd, DEVTYPE(dev), blockstart);
   1077 		if (rc < 0)	/* block test failed */
   1078 			return rc;
   1079 
   1080 		if (blockstart + erasesize > environment_end(dev)) {
   1081 			fprintf(stderr, "End of range reached, aborting\n");
   1082 			return -1;
   1083 		}
   1084 
   1085 		if (rc) {	/* block is bad */
   1086 			blockstart += blocklen;
   1087 			continue;
   1088 		}
   1089 
   1090 		if (DEVTYPE(dev) != MTD_ABSENT) {
   1091 			erase.start = blockstart;
   1092 			ioctl(fd, MEMUNLOCK, &erase);
   1093 			/* These do not need an explicit erase cycle */
   1094 			if (DEVTYPE(dev) != MTD_DATAFLASH)
   1095 				if (ioctl(fd, MEMERASE, &erase) != 0) {
   1096 					fprintf(stderr,
   1097 						"MTD erase error on %s: %s\n",
   1098 						DEVNAME(dev), strerror(errno));
   1099 					return -1;
   1100 				}
   1101 		}
   1102 
   1103 		if (lseek(fd, blockstart, SEEK_SET) == -1) {
   1104 			fprintf(stderr,
   1105 				"Seek error on %s: %s\n",
   1106 				DEVNAME(dev), strerror(errno));
   1107 			return -1;
   1108 		}
   1109 #ifdef DEBUG
   1110 		fprintf(stderr, "Write 0x%llx bytes at 0x%llx\n",
   1111 			(unsigned long long)erasesize,
   1112 			(unsigned long long)blockstart);
   1113 #endif
   1114 		if (write(fd, data + processed, erasesize) != erasesize) {
   1115 			fprintf(stderr, "Write error on %s: %s\n",
   1116 				DEVNAME(dev), strerror(errno));
   1117 			return -1;
   1118 		}
   1119 
   1120 		if (DEVTYPE(dev) != MTD_ABSENT)
   1121 			ioctl(fd, MEMLOCK, &erase);
   1122 
   1123 		processed += erasesize;
   1124 		block_seek = 0;
   1125 		blockstart += erasesize;
   1126 	}
   1127 
   1128 	if (write_total > count)
   1129 		free(data);
   1130 
   1131 	return processed;
   1132 }
   1133 
   1134 /*
   1135  * Set obsolete flag at offset - NOR flash only
   1136  */
   1137 static int flash_flag_obsolete(int dev, int fd, off_t offset)
   1138 {
   1139 	int rc;
   1140 	struct erase_info_user erase;
   1141 
   1142 	erase.start = DEVOFFSET(dev);
   1143 	erase.length = DEVESIZE(dev);
   1144 	/* This relies on the fact, that obsolete_flag == 0 */
   1145 	rc = lseek(fd, offset, SEEK_SET);
   1146 	if (rc < 0) {
   1147 		fprintf(stderr, "Cannot seek to set the flag on %s\n",
   1148 			DEVNAME(dev));
   1149 		return rc;
   1150 	}
   1151 	ioctl(fd, MEMUNLOCK, &erase);
   1152 	rc = write(fd, &obsolete_flag, sizeof(obsolete_flag));
   1153 	ioctl(fd, MEMLOCK, &erase);
   1154 	if (rc < 0)
   1155 		perror("Could not set obsolete flag");
   1156 
   1157 	return rc;
   1158 }
   1159 
   1160 static int flash_write(int fd_current, int fd_target, int dev_target)
   1161 {
   1162 	int rc;
   1163 
   1164 	switch (environment.flag_scheme) {
   1165 	case FLAG_NONE:
   1166 		break;
   1167 	case FLAG_INCREMENTAL:
   1168 		(*environment.flags)++;
   1169 		break;
   1170 	case FLAG_BOOLEAN:
   1171 		*environment.flags = active_flag;
   1172 		break;
   1173 	default:
   1174 		fprintf(stderr, "Unimplemented flash scheme %u\n",
   1175 			environment.flag_scheme);
   1176 		return -1;
   1177 	}
   1178 
   1179 #ifdef DEBUG
   1180 	fprintf(stderr, "Writing new environment at 0x%llx on %s\n",
   1181 		DEVOFFSET(dev_target), DEVNAME(dev_target));
   1182 #endif
   1183 
   1184 	if (IS_UBI(dev_target)) {
   1185 		if (ubi_update_start(fd_target, CUR_ENVSIZE) < 0)
   1186 			return 0;
   1187 		return ubi_write(fd_target, environment.image, CUR_ENVSIZE);
   1188 	}
   1189 
   1190 	rc = flash_write_buf(dev_target, fd_target, environment.image,
   1191 			     CUR_ENVSIZE);
   1192 	if (rc < 0)
   1193 		return rc;
   1194 
   1195 	if (environment.flag_scheme == FLAG_BOOLEAN) {
   1196 		/* Have to set obsolete flag */
   1197 		off_t offset = DEVOFFSET(dev_current) +
   1198 		    offsetof(struct env_image_redundant, flags);
   1199 #ifdef DEBUG
   1200 		fprintf(stderr,
   1201 			"Setting obsolete flag in environment at 0x%llx on %s\n",
   1202 			DEVOFFSET(dev_current), DEVNAME(dev_current));
   1203 #endif
   1204 		flash_flag_obsolete(dev_current, fd_current, offset);
   1205 	}
   1206 
   1207 	return 0;
   1208 }
   1209 
   1210 static int flash_read(int fd)
   1211 {
   1212 	int rc;
   1213 
   1214 	if (IS_UBI(dev_current)) {
   1215 		DEVTYPE(dev_current) = MTD_ABSENT;
   1216 
   1217 		return ubi_read(fd, environment.image, CUR_ENVSIZE);
   1218 	}
   1219 
   1220 	rc = flash_read_buf(dev_current, fd, environment.image, CUR_ENVSIZE,
   1221 			    DEVOFFSET(dev_current));
   1222 	if (rc != CUR_ENVSIZE)
   1223 		return -1;
   1224 
   1225 	return 0;
   1226 }
   1227 
   1228 static int flash_open_tempfile(const char **dname, const char **target_temp)
   1229 {
   1230 	char *dup_name = strdup(DEVNAME(dev_current));
   1231 	char *temp_name = NULL;
   1232 	int rc = -1;
   1233 
   1234 	if (!dup_name)
   1235 		return -1;
   1236 
   1237 	*dname = dirname(dup_name);
   1238 	if (!*dname)
   1239 		goto err;
   1240 
   1241 	rc = asprintf(&temp_name, "%s/XXXXXX", *dname);
   1242 	if (rc == -1)
   1243 		goto err;
   1244 
   1245 	rc = mkstemp(temp_name);
   1246 	if (rc == -1) {
   1247 		/* fall back to in place write */
   1248 		fprintf(stderr,
   1249 			"Can't create %s: %s\n", temp_name, strerror(errno));
   1250 		free(temp_name);
   1251 	} else {
   1252 		*target_temp = temp_name;
   1253 		/* deliberately leak dup_name as dname /might/ point into
   1254 		 * it and we need it for our caller
   1255 		 */
   1256 		dup_name = NULL;
   1257 	}
   1258 
   1259 err:
   1260 	if (dup_name)
   1261 		free(dup_name);
   1262 
   1263 	return rc;
   1264 }
   1265 
   1266 static int flash_io_write(int fd_current)
   1267 {
   1268 	int fd_target = -1, rc, dev_target;
   1269 	const char *dname, *target_temp = NULL;
   1270 
   1271 	if (have_redund_env) {
   1272 		/* switch to next partition for writing */
   1273 		dev_target = !dev_current;
   1274 		/* dev_target: fd_target, erase_target */
   1275 		fd_target = open(DEVNAME(dev_target), O_RDWR);
   1276 		if (fd_target < 0) {
   1277 			fprintf(stderr,
   1278 				"Can't open %s: %s\n",
   1279 				DEVNAME(dev_target), strerror(errno));
   1280 			rc = -1;
   1281 			goto exit;
   1282 		}
   1283 	} else {
   1284 		struct stat sb;
   1285 
   1286 		if (fstat(fd_current, &sb) == 0 && S_ISREG(sb.st_mode)) {
   1287 			/* if any part of flash_open_tempfile() fails we fall
   1288 			 * back to in-place writes
   1289 			 */
   1290 			fd_target = flash_open_tempfile(&dname, &target_temp);
   1291 		}
   1292 		dev_target = dev_current;
   1293 		if (fd_target == -1)
   1294 			fd_target = fd_current;
   1295 	}
   1296 
   1297 	rc = flash_write(fd_current, fd_target, dev_target);
   1298 
   1299 	if (fsync(fd_current) && !(errno == EINVAL || errno == EROFS)) {
   1300 		fprintf(stderr,
   1301 			"fsync failed on %s: %s\n",
   1302 			DEVNAME(dev_current), strerror(errno));
   1303 	}
   1304 
   1305 	if (fd_current != fd_target) {
   1306 		if (fsync(fd_target) &&
   1307 		    !(errno == EINVAL || errno == EROFS)) {
   1308 			fprintf(stderr,
   1309 				"fsync failed on %s: %s\n",
   1310 				DEVNAME(dev_current), strerror(errno));
   1311 		}
   1312 
   1313 		if (close(fd_target)) {
   1314 			fprintf(stderr,
   1315 				"I/O error on %s: %s\n",
   1316 				DEVNAME(dev_target), strerror(errno));
   1317 			rc = -1;
   1318 		}
   1319 
   1320 		if (target_temp) {
   1321 			int dir_fd;
   1322 
   1323 			dir_fd = open(dname, O_DIRECTORY | O_RDONLY);
   1324 			if (dir_fd == -1)
   1325 				fprintf(stderr,
   1326 					"Can't open %s: %s\n",
   1327 					dname, strerror(errno));
   1328 
   1329 			if (rename(target_temp, DEVNAME(dev_target))) {
   1330 				fprintf(stderr,
   1331 					"rename failed %s => %s: %s\n",
   1332 					target_temp, DEVNAME(dev_target),
   1333 					strerror(errno));
   1334 				rc = -1;
   1335 			}
   1336 
   1337 			if (dir_fd != -1 && fsync(dir_fd))
   1338 				fprintf(stderr,
   1339 					"fsync failed on %s: %s\n",
   1340 					dname, strerror(errno));
   1341 
   1342 			if (dir_fd != -1 && close(dir_fd))
   1343 				fprintf(stderr,
   1344 					"I/O error on %s: %s\n",
   1345 					dname, strerror(errno));
   1346 		}
   1347 	}
   1348  exit:
   1349 	return rc;
   1350 }
   1351 
   1352 static int flash_io(int mode)
   1353 {
   1354 	int fd_current, rc;
   1355 
   1356 	/* dev_current: fd_current, erase_current */
   1357 	fd_current = open(DEVNAME(dev_current), mode);
   1358 	if (fd_current < 0) {
   1359 		fprintf(stderr,
   1360 			"Can't open %s: %s\n",
   1361 			DEVNAME(dev_current), strerror(errno));
   1362 		return -1;
   1363 	}
   1364 
   1365 	if (mode == O_RDWR) {
   1366 		rc = flash_io_write(fd_current);
   1367 	} else {
   1368 		rc = flash_read(fd_current);
   1369 	}
   1370 
   1371 	if (close(fd_current)) {
   1372 		fprintf(stderr,
   1373 			"I/O error on %s: %s\n",
   1374 			DEVNAME(dev_current), strerror(errno));
   1375 		return -1;
   1376 	}
   1377 
   1378 	return rc;
   1379 }
   1380 
   1381 /*
   1382  * Prevent confusion if running from erased flash memory
   1383  */
   1384 int fw_env_open(struct env_opts *opts)
   1385 {
   1386 	int crc0, crc0_ok;
   1387 	unsigned char flag0;
   1388 	void *addr0 = NULL;
   1389 
   1390 	int crc1, crc1_ok;
   1391 	unsigned char flag1;
   1392 	void *addr1 = NULL;
   1393 
   1394 	int ret;
   1395 
   1396 	struct env_image_single *single;
   1397 	struct env_image_redundant *redundant;
   1398 
   1399 	if (!opts)
   1400 		opts = &default_opts;
   1401 
   1402 	if (parse_config(opts))	/* should fill envdevices */
   1403 		return -EINVAL;
   1404 
   1405 	addr0 = calloc(1, CUR_ENVSIZE);
   1406 	if (addr0 == NULL) {
   1407 		fprintf(stderr,
   1408 			"Not enough memory for environment (%ld bytes)\n",
   1409 			CUR_ENVSIZE);
   1410 		ret = -ENOMEM;
   1411 		goto open_cleanup;
   1412 	}
   1413 
   1414 	/* read environment from FLASH to local buffer */
   1415 	environment.image = addr0;
   1416 
   1417 	if (have_redund_env) {
   1418 		redundant = addr0;
   1419 		environment.crc = &redundant->crc;
   1420 		environment.flags = &redundant->flags;
   1421 		environment.data = redundant->data;
   1422 	} else {
   1423 		single = addr0;
   1424 		environment.crc = &single->crc;
   1425 		environment.flags = NULL;
   1426 		environment.data = single->data;
   1427 	}
   1428 
   1429 	dev_current = 0;
   1430 	if (flash_io(O_RDONLY)) {
   1431 		ret = -EIO;
   1432 		goto open_cleanup;
   1433 	}
   1434 
   1435 	crc0 = crc32(0, (uint8_t *)environment.data, ENV_SIZE);
   1436 
   1437 	crc0_ok = (crc0 == *environment.crc);
   1438 	if (!have_redund_env) {
   1439 		if (!crc0_ok) {
   1440 			fprintf(stderr,
   1441 				"Warning: Bad CRC, using default environment\n");
   1442 			memcpy(environment.data, default_environment,
   1443 			       sizeof(default_environment));
   1444 		}
   1445 	} else {
   1446 		flag0 = *environment.flags;
   1447 
   1448 		dev_current = 1;
   1449 		addr1 = calloc(1, CUR_ENVSIZE);
   1450 		if (addr1 == NULL) {
   1451 			fprintf(stderr,
   1452 				"Not enough memory for environment (%ld bytes)\n",
   1453 				CUR_ENVSIZE);
   1454 			ret = -ENOMEM;
   1455 			goto open_cleanup;
   1456 		}
   1457 		redundant = addr1;
   1458 
   1459 		/*
   1460 		 * have to set environment.image for flash_read(), careful -
   1461 		 * other pointers in environment still point inside addr0
   1462 		 */
   1463 		environment.image = addr1;
   1464 		if (flash_io(O_RDONLY)) {
   1465 			ret = -EIO;
   1466 			goto open_cleanup;
   1467 		}
   1468 
   1469 		/* Check flag scheme compatibility */
   1470 		if (DEVTYPE(dev_current) == MTD_NORFLASH &&
   1471 		    DEVTYPE(!dev_current) == MTD_NORFLASH) {
   1472 			environment.flag_scheme = FLAG_BOOLEAN;
   1473 		} else if (DEVTYPE(dev_current) == MTD_NANDFLASH &&
   1474 			   DEVTYPE(!dev_current) == MTD_NANDFLASH) {
   1475 			environment.flag_scheme = FLAG_INCREMENTAL;
   1476 		} else if (DEVTYPE(dev_current) == MTD_DATAFLASH &&
   1477 			   DEVTYPE(!dev_current) == MTD_DATAFLASH) {
   1478 			environment.flag_scheme = FLAG_BOOLEAN;
   1479 		} else if (DEVTYPE(dev_current) == MTD_UBIVOLUME &&
   1480 			   DEVTYPE(!dev_current) == MTD_UBIVOLUME) {
   1481 			environment.flag_scheme = FLAG_INCREMENTAL;
   1482 		} else if (DEVTYPE(dev_current) == MTD_ABSENT &&
   1483 			   DEVTYPE(!dev_current) == MTD_ABSENT &&
   1484 			   IS_UBI(dev_current) == IS_UBI(!dev_current)) {
   1485 			environment.flag_scheme = FLAG_INCREMENTAL;
   1486 		} else {
   1487 			fprintf(stderr, "Incompatible flash types!\n");
   1488 			ret = -EINVAL;
   1489 			goto open_cleanup;
   1490 		}
   1491 
   1492 		crc1 = crc32(0, (uint8_t *)redundant->data, ENV_SIZE);
   1493 
   1494 		crc1_ok = (crc1 == redundant->crc);
   1495 		flag1 = redundant->flags;
   1496 
   1497 		if (crc0_ok && !crc1_ok) {
   1498 			dev_current = 0;
   1499 		} else if (!crc0_ok && crc1_ok) {
   1500 			dev_current = 1;
   1501 		} else if (!crc0_ok && !crc1_ok) {
   1502 			fprintf(stderr,
   1503 				"Warning: Bad CRC, using default environment\n");
   1504 			memcpy(environment.data, default_environment,
   1505 			       sizeof(default_environment));
   1506 			dev_current = 0;
   1507 		} else {
   1508 			switch (environment.flag_scheme) {
   1509 			case FLAG_BOOLEAN:
   1510 				if (flag0 == active_flag &&
   1511 				    flag1 == obsolete_flag) {
   1512 					dev_current = 0;
   1513 				} else if (flag0 == obsolete_flag &&
   1514 					   flag1 == active_flag) {
   1515 					dev_current = 1;
   1516 				} else if (flag0 == flag1) {
   1517 					dev_current = 0;
   1518 				} else if (flag0 == 0xFF) {
   1519 					dev_current = 0;
   1520 				} else if (flag1 == 0xFF) {
   1521 					dev_current = 1;
   1522 				} else {
   1523 					dev_current = 0;
   1524 				}
   1525 				break;
   1526 			case FLAG_INCREMENTAL:
   1527 				if (flag0 == 255 && flag1 == 0)
   1528 					dev_current = 1;
   1529 				else if ((flag1 == 255 && flag0 == 0) ||
   1530 					 flag0 >= flag1)
   1531 					dev_current = 0;
   1532 				else	/* flag1 > flag0 */
   1533 					dev_current = 1;
   1534 				break;
   1535 			default:
   1536 				fprintf(stderr, "Unknown flag scheme %u\n",
   1537 					environment.flag_scheme);
   1538 				return -1;
   1539 			}
   1540 		}
   1541 
   1542 		/*
   1543 		 * If we are reading, we don't need the flag and the CRC any
   1544 		 * more, if we are writing, we will re-calculate CRC and update
   1545 		 * flags before writing out
   1546 		 */
   1547 		if (dev_current) {
   1548 			environment.image = addr1;
   1549 			environment.crc = &redundant->crc;
   1550 			environment.flags = &redundant->flags;
   1551 			environment.data = redundant->data;
   1552 			free(addr0);
   1553 		} else {
   1554 			environment.image = addr0;
   1555 			/* Other pointers are already set */
   1556 			free(addr1);
   1557 		}
   1558 #ifdef DEBUG
   1559 		fprintf(stderr, "Selected env in %s\n", DEVNAME(dev_current));
   1560 #endif
   1561 	}
   1562 	return 0;
   1563 
   1564  open_cleanup:
   1565 	if (addr0)
   1566 		free(addr0);
   1567 
   1568 	if (addr1)
   1569 		free(addr0);
   1570 
   1571 	return ret;
   1572 }
   1573 
   1574 /*
   1575  * Simply free allocated buffer with environment
   1576  */
   1577 int fw_env_close(struct env_opts *opts)
   1578 {
   1579 	if (environment.image)
   1580 		free(environment.image);
   1581 
   1582 	environment.image = NULL;
   1583 
   1584 	return 0;
   1585 }
   1586 
   1587 static int check_device_config(int dev)
   1588 {
   1589 	struct stat st;
   1590 	int32_t lnum = 0;
   1591 	int fd, rc = 0;
   1592 
   1593 	/* Fills in IS_UBI(), converts DEVNAME() with ubi volume name */
   1594 	ubi_check_dev(dev);
   1595 
   1596 	fd = open(DEVNAME(dev), O_RDONLY);
   1597 	if (fd < 0) {
   1598 		fprintf(stderr,
   1599 			"Cannot open %s: %s\n", DEVNAME(dev), strerror(errno));
   1600 		return -1;
   1601 	}
   1602 
   1603 	rc = fstat(fd, &st);
   1604 	if (rc < 0) {
   1605 		fprintf(stderr, "Cannot stat the file %s\n", DEVNAME(dev));
   1606 		goto err;
   1607 	}
   1608 
   1609 	if (IS_UBI(dev)) {
   1610 		rc = ioctl(fd, UBI_IOCEBISMAP, &lnum);
   1611 		if (rc < 0) {
   1612 			fprintf(stderr, "Cannot get UBI information for %s\n",
   1613 				DEVNAME(dev));
   1614 			goto err;
   1615 		}
   1616 	} else if (S_ISCHR(st.st_mode)) {
   1617 		struct mtd_info_user mtdinfo;
   1618 		rc = ioctl(fd, MEMGETINFO, &mtdinfo);
   1619 		if (rc < 0) {
   1620 			fprintf(stderr, "Cannot get MTD information for %s\n",
   1621 				DEVNAME(dev));
   1622 			goto err;
   1623 		}
   1624 		if (mtdinfo.type != MTD_NORFLASH &&
   1625 		    mtdinfo.type != MTD_NANDFLASH &&
   1626 		    mtdinfo.type != MTD_DATAFLASH &&
   1627 		    mtdinfo.type != MTD_UBIVOLUME) {
   1628 			fprintf(stderr, "Unsupported flash type %u on %s\n",
   1629 				mtdinfo.type, DEVNAME(dev));
   1630 			goto err;
   1631 		}
   1632 		DEVTYPE(dev) = mtdinfo.type;
   1633 		if (DEVESIZE(dev) == 0)
   1634 			/* Assume the erase size is the same as the env-size */
   1635 			DEVESIZE(dev) = ENVSIZE(dev);
   1636 	} else {
   1637 		uint64_t size;
   1638 		DEVTYPE(dev) = MTD_ABSENT;
   1639 		if (DEVESIZE(dev) == 0)
   1640 			/* Assume the erase size to be 512 bytes */
   1641 			DEVESIZE(dev) = 0x200;
   1642 
   1643 		/*
   1644 		 * Check for negative offsets, treat it as backwards offset
   1645 		 * from the end of the block device
   1646 		 */
   1647 		if (DEVOFFSET(dev) < 0) {
   1648 			rc = ioctl(fd, BLKGETSIZE64, &size);
   1649 			if (rc < 0) {
   1650 				fprintf(stderr,
   1651 					"Could not get block device size on %s\n",
   1652 					DEVNAME(dev));
   1653 				goto err;
   1654 			}
   1655 
   1656 			DEVOFFSET(dev) = DEVOFFSET(dev) + size;
   1657 #ifdef DEBUG
   1658 			fprintf(stderr,
   1659 				"Calculated device offset 0x%llx on %s\n",
   1660 				DEVOFFSET(dev), DEVNAME(dev));
   1661 #endif
   1662 		}
   1663 	}
   1664 
   1665 	if (ENVSECTORS(dev) == 0)
   1666 		/* Assume enough sectors to cover the environment */
   1667 		ENVSECTORS(dev) = DIV_ROUND_UP(ENVSIZE(dev), DEVESIZE(dev));
   1668 
   1669 	if (DEVOFFSET(dev) % DEVESIZE(dev) != 0) {
   1670 		fprintf(stderr,
   1671 			"Environment does not start on (erase) block boundary\n");
   1672 		errno = EINVAL;
   1673 		return -1;
   1674 	}
   1675 
   1676 	if (ENVSIZE(dev) > ENVSECTORS(dev) * DEVESIZE(dev)) {
   1677 		fprintf(stderr,
   1678 			"Environment does not fit into available sectors\n");
   1679 		errno = EINVAL;
   1680 		return -1;
   1681 	}
   1682 
   1683  err:
   1684 	close(fd);
   1685 	return rc;
   1686 }
   1687 
   1688 static int parse_config(struct env_opts *opts)
   1689 {
   1690 	int rc;
   1691 
   1692 	if (!opts)
   1693 		opts = &default_opts;
   1694 
   1695 #if defined(CONFIG_FILE)
   1696 	/* Fills in DEVNAME(), ENVSIZE(), DEVESIZE(). Or don't. */
   1697 	if (get_config(opts->config_file)) {
   1698 		fprintf(stderr, "Cannot parse config file '%s': %m\n",
   1699 			opts->config_file);
   1700 		return -1;
   1701 	}
   1702 #else
   1703 	DEVNAME(0) = DEVICE1_NAME;
   1704 	DEVOFFSET(0) = DEVICE1_OFFSET;
   1705 	ENVSIZE(0) = ENV1_SIZE;
   1706 
   1707 	/* Set defaults for DEVESIZE, ENVSECTORS later once we
   1708 	 * know DEVTYPE
   1709 	 */
   1710 #ifdef DEVICE1_ESIZE
   1711 	DEVESIZE(0) = DEVICE1_ESIZE;
   1712 #endif
   1713 #ifdef DEVICE1_ENVSECTORS
   1714 	ENVSECTORS(0) = DEVICE1_ENVSECTORS;
   1715 #endif
   1716 
   1717 #ifdef HAVE_REDUND
   1718 	DEVNAME(1) = DEVICE2_NAME;
   1719 	DEVOFFSET(1) = DEVICE2_OFFSET;
   1720 	ENVSIZE(1) = ENV2_SIZE;
   1721 
   1722 	/* Set defaults for DEVESIZE, ENVSECTORS later once we
   1723 	 * know DEVTYPE
   1724 	 */
   1725 #ifdef DEVICE2_ESIZE
   1726 	DEVESIZE(1) = DEVICE2_ESIZE;
   1727 #endif
   1728 #ifdef DEVICE2_ENVSECTORS
   1729 	ENVSECTORS(1) = DEVICE2_ENVSECTORS;
   1730 #endif
   1731 	have_redund_env = 1;
   1732 #endif
   1733 #endif
   1734 	rc = check_device_config(0);
   1735 	if (rc < 0)
   1736 		return rc;
   1737 
   1738 	if (have_redund_env) {
   1739 		rc = check_device_config(1);
   1740 		if (rc < 0)
   1741 			return rc;
   1742 
   1743 		if (ENVSIZE(0) != ENVSIZE(1)) {
   1744 			fprintf(stderr,
   1745 				"Redundant environments have unequal size");
   1746 			return -1;
   1747 		}
   1748 	}
   1749 
   1750 	usable_envsize = CUR_ENVSIZE - sizeof(uint32_t);
   1751 	if (have_redund_env)
   1752 		usable_envsize -= sizeof(char);
   1753 
   1754 	return 0;
   1755 }
   1756 
   1757 #if defined(CONFIG_FILE)
   1758 static int get_config(char *fname)
   1759 {
   1760 	FILE *fp;
   1761 	int i = 0;
   1762 	int rc;
   1763 	char *line = NULL;
   1764 	size_t linesize = 0;
   1765 	char *devname;
   1766 
   1767 	fp = fopen(fname, "r");
   1768 	if (fp == NULL)
   1769 		return -1;
   1770 
   1771 	while (i < 2 && getline(&line, &linesize, fp) != -1) {
   1772 		/* Skip comment strings */
   1773 		if (line[0] == '#')
   1774 			continue;
   1775 
   1776 		rc = sscanf(line, "%ms %lli %lx %lx %lx",
   1777 			    &devname,
   1778 			    &DEVOFFSET(i),
   1779 			    &ENVSIZE(i), &DEVESIZE(i), &ENVSECTORS(i));
   1780 
   1781 		if (rc < 3)
   1782 			continue;
   1783 
   1784 		DEVNAME(i) = devname;
   1785 
   1786 		/* Set defaults for DEVESIZE, ENVSECTORS later once we
   1787 		 * know DEVTYPE
   1788 		 */
   1789 
   1790 		i++;
   1791 	}
   1792 	free(line);
   1793 	fclose(fp);
   1794 
   1795 	have_redund_env = i - 1;
   1796 	if (!i) {		/* No valid entries found */
   1797 		errno = EINVAL;
   1798 		return -1;
   1799 	} else
   1800 		return 0;
   1801 }
   1802 #endif
   1803