File:  [ELWIX - Embedded LightWeight unIX -] / embedtools / src / ub_env.c
Revision 1.1.2.12: download - view: text, annotated - select for diffs - revision graph
Wed Jan 29 13:31:13 2014 UTC (10 years, 4 months ago) by misho
Branches: tools2_0
add crc check

#include "global.h"
#include "ub_env.h"


env_t *env;

static int
ub_flash_io(const char *csSec, int mode)
{
	int f, l, rlen;
	const char *str;
	size_t siz, esiz;
	ait_val_t v;
	u_int crc;

	FTRACE(4);

	str = cfg_getAttribute(&cfg, csSec, "drive_size");
	siz = strtol(str, NULL, 0);
	if (!siz)
		return -1;
	str = cfg_getAttribute(&cfg, csSec, "env_size");
	if (!str)
		esiz = siz - sizeof env->env_crc;
	else
		esiz = strtol(str, NULL, 0);
	str = cfg_getAttribute(&cfg, csSec, "drive_name");
	if (!str) {
		printf("Error:: drive not found!\n");
		return -1;
	}

	cfg_loadAttribute(&cfg, "ube", "lock", &v, UBE_LOCK);
	l = open(AIT_GET_STR(&v), O_CREAT | O_EXCL | O_WRONLY, 0644);
	if (l == -1) {
		printf("Error:: Locked u-boot-env map %s\n", AIT_GET_STR(&v));
		AIT_FREE_VAL(&v);
		return -1;
	}

	f = open(str, mode);
	if (f == -1) {
		printf("Error:: Can't access u-boot-env device %s\n", str);
		close(l);
		unlink(AIT_GET_STR(&v));
		AIT_FREE_VAL(&v);
		return -1;
	}

	if (mode & O_RDWR) {
		rlen = write(f, env, siz);
		if (rlen != siz)
			printf("Error:: written %d bytes != %d\n", rlen, siz);
		else
			VERB(3) printf("Written %d bytes\n", rlen);
		lseek(f, 0, SEEK_SET);
	}

	rlen = read(f, env, siz);
	if (rlen != siz)
		printf("Error:: readed %d bytes != %d\n", rlen, siz);
	else
		VERB(3) printf("Readed %d bytes\n", rlen);

	crc = crc32(0, (u_char*) env->env_data, esiz);
	if (crc != env->env_crc)
		VERB(1) printf("Warning:: Flash crc32 0x%x != 0x%x - "
				"Bad CRC, using default environment\n", env->env_crc, crc);

	close(f);
	close(l);
	unlink(AIT_GET_STR(&v));
	AIT_FREE_VAL(&v);
	return 0;
}

static inline const char *
ub_envmatch(const char *csName, const char *e)
{
	while (*csName == *e++)
		if (*csName++ == '=')
			return e;
	if (!*csName && *(e - 1) == '=')
		return e;

	return NULL;
}

int
ub_load(const char *csSec)
{
	const char *str;
	size_t siz;

	FTRACE(4);

	str = cfg_getAttribute(&cfg, csSec, "drive_size");
	siz = strtol(str, NULL, 0);
	if (!siz)
		return -1;

	env = e_malloc(siz);
	if (!env) {
		ELIBERR(elwix);
		return -1;
	}

	return ub_flash_io(csSec, O_RDONLY);
}

void
ub_unload()
{
	FTRACE(4);

	if (env)
		e_free(env);
}

const char*
ub_getenv(const char *csSec, const char *csName)
{
	char *e, *nxt;
	size_t dlen;
	const char *str = NULL;

	FTRACE(3);

	str = cfg_getAttribute(&cfg, csSec, "env_size");
	if (!str) {
		str = cfg_getAttribute(&cfg, csSec, "drive_size");
		if (!str)
			return -1;
	}
	dlen = strtol(str, NULL, 0);
	if (!dlen)
		return NULL;
	else
		dlen--;

	for (e = env->env_data; *e; e = nxt + 1) {
		for (nxt = e; *nxt; nxt++)
			if (nxt >= env->env_data + dlen) {
				printf("Error:: environment not terminated\n");
				return NULL;
			}

		str = ub_envmatch(csName, e);
		if (str)
			break;
	}

	return str;
}

int
ub_setenv(const char *csSec, const char *csName, const char *csValue)
{
	char *e, *nxt;
	size_t dlen, len;
	const char *str, *old = NULL;

	FTRACE(3);

	str = cfg_getAttribute(&cfg, csSec, "env_size");
	if (!str) {
		str = cfg_getAttribute(&cfg, csSec, "drive_size");
		if (!str)
			return -1;
	}
	dlen = strtol(str, NULL, 0);
	if (!dlen)
		return -1;
	else
		dlen--;

	for (e = env->env_data; *e; e = nxt + 1) {
		for (nxt = e; *nxt; nxt++)
			if (nxt >= env->env_data + dlen) {
				printf("Error:: environment not terminated\n");
				return -1;
			}

		old = ub_envmatch(csName, e);
		if (old)
			break;
	}

	/* Delete any existing definition */
	if (old) {
		if (!*++nxt)
			*e = 0;
		else
			while (42) {
				*e = *nxt++;
				if (!*e && !*nxt)
					break;
				e++;
			}
		*++e = 0;
	}

	if (csValue) {
		/* Append new definition at the end */
		for (e = env->env_data; *e || *(e + 1); e++);
		if (e > env->env_data)
			e++;
		/* "name" + "=" + "val" +"\0\0"  > u-boot-env size */
		len = strlen(csName) + 2; /* add '=' for first arg, ' ' for all others */
		len += strlen(csValue) + 1;
		if (len > env->env_data + dlen - e) {
			printf("Error:: Environment overflow!\n");
			return -1;
		}

		/* av pair */
		while ((*e = *csName++))
			e++;
		*e = '=';
		while ((*++e = *csValue++));

		/* end is marked with double '\0' */
		*++e = 0;
	}

	if (ub_flash_io(csSec, O_RDWR)) {
		printf("Error:: Can't write environment to flash!\n");
		return -1;
	}

	return 0;
}

int
ub_env(const char *csSec)
{
	char *e, *nxt;
	size_t dlen;
	const char *str;

	FTRACE(3);

	str = cfg_getAttribute(&cfg, csSec, "env_size");
	if (!str) {
		str = cfg_getAttribute(&cfg, csSec, "drive_size");
		if (!str)
			return -1;
	}
	dlen = strtol(str, NULL, 0);
	if (!dlen)
		return -1;
	else
		dlen--;

	for (e = env->env_data; *e; e = nxt + 1) {
		for (nxt = e; *nxt; nxt++)
			if (nxt >= env->env_data + dlen) {
				printf("Error:: environment not terminated\n");
				return -1;
			}

		printf("%s\n", e);
	}

	return 0;
}

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>