diff options
Diffstat (limited to 'common/env_eeprom.c')
| -rw-r--r-- | common/env_eeprom.c | 131 | 
1 files changed, 127 insertions, 4 deletions
| diff --git a/common/env_eeprom.c b/common/env_eeprom.c index 30de4e9ca..95a7d0d3b 100644 --- a/common/env_eeprom.c +++ b/common/env_eeprom.c @@ -32,6 +32,11 @@  #include <i2c.h>  #endif +#ifdef CONFIG_ENV_OFFSET_REDUND +#define ACTIVE_FLAG   1 +#define OBSOLETE_FLAG 0 +#endif +  DECLARE_GLOBAL_DATA_PTR;  env_t *env_ptr = NULL; @@ -93,9 +98,15 @@ static int eeprom_bus_write (unsigned dev_addr, unsigned offset, uchar *buffer,  uchar env_get_char_spec (int index)  {  	uchar c; +	unsigned int off; +	off = CONFIG_ENV_OFFSET; +#ifdef CONFIG_ENV_OFFSET_REDUND +	if (gd->env_valid == 2) +		off = CONFIG_ENV_OFFSET_REDUND; +#endif  	eeprom_bus_read (CONFIG_SYS_DEF_EEPROM_ADDR, -		     CONFIG_ENV_OFFSET+index+offsetof(env_t,data), +		     off + index + offsetof(env_t,data),  		     &c, 1);  	return (c); @@ -103,18 +114,52 @@ uchar env_get_char_spec (int index)  void env_relocate_spec (void)  { +	unsigned int off = CONFIG_ENV_OFFSET; +#ifdef CONFIG_ENV_OFFSET_REDUND +	if (gd->env_valid == 2) +		off = CONFIG_ENV_OFFSET_REDUND; +#endif  	eeprom_bus_read (CONFIG_SYS_DEF_EEPROM_ADDR, -		     CONFIG_ENV_OFFSET, +		     off,  		     (uchar*)env_ptr,  		     CONFIG_ENV_SIZE);  }  int saveenv(void)  { -	return eeprom_bus_write (CONFIG_SYS_DEF_EEPROM_ADDR, -			     CONFIG_ENV_OFFSET, +	int rc; +	unsigned int off = CONFIG_ENV_OFFSET; +#ifdef CONFIG_ENV_OFFSET_REDUND +	unsigned int off_red = CONFIG_ENV_OFFSET_REDUND; +	char flag_obsolete = OBSOLETE_FLAG; +	if (gd->env_valid == 1) { +		off = CONFIG_ENV_OFFSET_REDUND; +		off_red = CONFIG_ENV_OFFSET; +	} + +	env_ptr->flags = ACTIVE_FLAG; +#endif + +	rc = eeprom_bus_write (CONFIG_SYS_DEF_EEPROM_ADDR, +			     off,  			     (uchar *)env_ptr,  			     CONFIG_ENV_SIZE); + +#ifdef CONFIG_ENV_OFFSET_REDUND +	if (rc == 0) { +		eeprom_bus_write (CONFIG_SYS_DEF_EEPROM_ADDR, +				  off_red + offsetof(env_t,flags), +				  (uchar *)&flag_obsolete, +				  1); +		if (gd->env_valid == 1) +			gd->env_valid = 2; +		else +			gd->env_valid = 1; + +	} +#endif + +	return rc;  }  /************************************************************************ @@ -123,6 +168,82 @@ int saveenv(void)   * We are still running from ROM, so data use is limited   * Use a (moderately small) buffer on the stack   */ + +#ifdef CONFIG_ENV_OFFSET_REDUND +int env_init(void) +{ +	ulong len; +	ulong crc[2], crc_tmp; +	unsigned int off, off_env[2]; +	uchar buf[64]; +	int crc_ok[2] = {0,0}; +	unsigned char flags[2]; +	int i; + +	eeprom_init ();	/* prepare for EEPROM read/write */ + +	off_env[0] = CONFIG_ENV_OFFSET; +	off_env[1] = CONFIG_ENV_OFFSET_REDUND; + +	for (i = 0; i < 2; i++) { +		/* read CRC */ +		eeprom_bus_read (CONFIG_SYS_DEF_EEPROM_ADDR, +			off_env[i] + offsetof(env_t,crc), +			(uchar *)&crc[i], sizeof(ulong)); +		/* read FLAGS */ +		eeprom_bus_read (CONFIG_SYS_DEF_EEPROM_ADDR, +			off_env[i] + offsetof(env_t,flags), +			(uchar *)&flags[i], sizeof(uchar)); + +		crc_tmp= 0; +		len = ENV_SIZE; +		off = off_env[i] + offsetof(env_t,data); +		while (len > 0) { +			int n = (len > sizeof(buf)) ? sizeof(buf) : len; + +			eeprom_bus_read (CONFIG_SYS_DEF_EEPROM_ADDR, off, +				buf, n); + +			crc_tmp = crc32 (crc_tmp, buf, n); +			len -= n; +			off += n; +		} +		if (crc_tmp == crc[i]) +			crc_ok[i] = 1; +	} + +	if (!crc_ok[0] && !crc_ok[1]) { +		gd->env_addr  = 0; +		gd->env_valid = 0; + +		return 0; +	} else if (crc_ok[0] && !crc_ok[1]) { +		gd->env_valid = 1; +	} +	else if (!crc_ok[0] && crc_ok[1]) { +		gd->env_valid = 2; +	} else { +		/* both ok - check serial */ +		if (flags[0] == ACTIVE_FLAG && flags[1] == OBSOLETE_FLAG) +			gd->env_valid = 1; +		else if (flags[0] == OBSOLETE_FLAG && flags[1] == ACTIVE_FLAG) +			gd->env_valid = 2; +		else if (flags[0] == 0xFF && flags[1] == 0) +			gd->env_valid = 2; +		else if(flags[1] == 0xFF && flags[0] == 0) +			gd->env_valid = 1; +		else /* flags are equal - almost impossible */ +			gd->env_valid = 1; +	} + +	if (gd->env_valid == 2) +		gd->env_addr = off_env[1] + offsetof(env_t,data); +	else if (gd->env_valid == 1) +		gd->env_addr = off_env[0] + offsetof(env_t,data); + +	return (0); +} +#else  int env_init(void)  {  	ulong crc, len, new; @@ -159,3 +280,5 @@ int env_init(void)  	return (0);  } +#endif + |