mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-12-05 02:51:00 +00:00
83d290c56f
When U-Boot started using SPDX tags we were among the early adopters and there weren't a lot of other examples to borrow from. So we picked the area of the file that usually had a full license text and replaced it with an appropriate SPDX-License-Identifier: entry. Since then, the Linux Kernel has adopted SPDX tags and they place it as the very first line in a file (except where shebangs are used, then it's second line) and with slightly different comment styles than us. In part due to community overlap, in part due to better tag visibility and in part for other minor reasons, switch over to that style. This commit changes all instances where we have a single declared license in the tag as both the before and after are identical in tag contents. There's also a few places where I found we did not have a tag and have introduced one. Signed-off-by: Tom Rini <trini@konsulko.com>
235 lines
5.3 KiB
C
235 lines
5.3 KiB
C
// SPDX-License-Identifier: GPL-2.0+
|
|
/*
|
|
* (C) Copyright 2000-2010
|
|
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
|
*
|
|
* (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
|
|
* Andreas Heppel <aheppel@sysgo.de>
|
|
*/
|
|
|
|
#include <common.h>
|
|
#include <command.h>
|
|
#include <environment.h>
|
|
#include <linux/stddef.h>
|
|
#if defined(CONFIG_I2C_ENV_EEPROM_BUS)
|
|
#include <i2c.h>
|
|
#endif
|
|
#include <search.h>
|
|
#include <errno.h>
|
|
#include <linux/compiler.h> /* for BUG_ON */
|
|
|
|
DECLARE_GLOBAL_DATA_PTR;
|
|
|
|
static int eeprom_bus_read(unsigned dev_addr, unsigned offset,
|
|
uchar *buffer, unsigned cnt)
|
|
{
|
|
int rcode;
|
|
#if defined(CONFIG_I2C_ENV_EEPROM_BUS)
|
|
int old_bus = i2c_get_bus_num();
|
|
|
|
if (old_bus != CONFIG_I2C_ENV_EEPROM_BUS)
|
|
i2c_set_bus_num(CONFIG_I2C_ENV_EEPROM_BUS);
|
|
#endif
|
|
|
|
rcode = eeprom_read(dev_addr, offset, buffer, cnt);
|
|
|
|
#if defined(CONFIG_I2C_ENV_EEPROM_BUS)
|
|
i2c_set_bus_num(old_bus);
|
|
#endif
|
|
|
|
return rcode;
|
|
}
|
|
|
|
static int eeprom_bus_write(unsigned dev_addr, unsigned offset,
|
|
uchar *buffer, unsigned cnt)
|
|
{
|
|
int rcode;
|
|
#if defined(CONFIG_I2C_ENV_EEPROM_BUS)
|
|
int old_bus = i2c_get_bus_num();
|
|
|
|
if (old_bus != CONFIG_I2C_ENV_EEPROM_BUS)
|
|
i2c_set_bus_num(CONFIG_I2C_ENV_EEPROM_BUS);
|
|
#endif
|
|
|
|
rcode = eeprom_write(dev_addr, offset, buffer, cnt);
|
|
|
|
#if defined(CONFIG_I2C_ENV_EEPROM_BUS)
|
|
i2c_set_bus_num(old_bus);
|
|
#endif
|
|
|
|
return rcode;
|
|
}
|
|
|
|
/** Call this function from overridden env_get_char_spec() if you need
|
|
* this functionality.
|
|
*/
|
|
int env_eeprom_get_char(int index)
|
|
{
|
|
uchar c;
|
|
unsigned int off = CONFIG_ENV_OFFSET;
|
|
|
|
#ifdef CONFIG_ENV_OFFSET_REDUND
|
|
if (gd->env_valid == ENV_REDUND)
|
|
off = CONFIG_ENV_OFFSET_REDUND;
|
|
#endif
|
|
eeprom_bus_read(CONFIG_SYS_DEF_EEPROM_ADDR,
|
|
off + index + offsetof(env_t, data), &c, 1);
|
|
|
|
return c;
|
|
}
|
|
|
|
static int env_eeprom_load(void)
|
|
{
|
|
char buf_env[CONFIG_ENV_SIZE];
|
|
unsigned int off = CONFIG_ENV_OFFSET;
|
|
|
|
#ifdef CONFIG_ENV_OFFSET_REDUND
|
|
ulong len, crc[2], crc_tmp;
|
|
unsigned int off_env[2];
|
|
uchar rdbuf[64], flags[2];
|
|
int i, crc_ok[2] = {0, 0};
|
|
|
|
eeprom_init(-1); /* 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(rdbuf)) ? sizeof(rdbuf) : len;
|
|
|
|
eeprom_bus_read(CONFIG_SYS_DEF_EEPROM_ADDR, off,
|
|
rdbuf, n);
|
|
|
|
crc_tmp = crc32(crc_tmp, rdbuf, 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 = ENV_INVALID;
|
|
} else if (crc_ok[0] && !crc_ok[1]) {
|
|
gd->env_valid = ENV_VALID;
|
|
} else if (!crc_ok[0] && crc_ok[1]) {
|
|
gd->env_valid = ENV_REDUND;
|
|
} else {
|
|
/* both ok - check serial */
|
|
if (flags[0] == ACTIVE_FLAG && flags[1] == OBSOLETE_FLAG)
|
|
gd->env_valid = ENV_VALID;
|
|
else if (flags[0] == OBSOLETE_FLAG && flags[1] == ACTIVE_FLAG)
|
|
gd->env_valid = ENV_REDUND;
|
|
else if (flags[0] == 0xFF && flags[1] == 0)
|
|
gd->env_valid = ENV_REDUND;
|
|
else if (flags[1] == 0xFF && flags[0] == 0)
|
|
gd->env_valid = ENV_VALID;
|
|
else /* flags are equal - almost impossible */
|
|
gd->env_valid = ENV_VALID;
|
|
}
|
|
|
|
#else /* CONFIG_ENV_OFFSET_REDUND */
|
|
ulong crc, len, new;
|
|
uchar rdbuf[64];
|
|
|
|
eeprom_init(-1); /* prepare for EEPROM read/write */
|
|
|
|
/* read old CRC */
|
|
eeprom_bus_read(CONFIG_SYS_DEF_EEPROM_ADDR,
|
|
CONFIG_ENV_OFFSET + offsetof(env_t, crc),
|
|
(uchar *)&crc, sizeof(ulong));
|
|
|
|
new = 0;
|
|
len = ENV_SIZE;
|
|
off = offsetof(env_t, data);
|
|
while (len > 0) {
|
|
int n = (len > sizeof(rdbuf)) ? sizeof(rdbuf) : len;
|
|
|
|
eeprom_bus_read(CONFIG_SYS_DEF_EEPROM_ADDR,
|
|
CONFIG_ENV_OFFSET + off, rdbuf, n);
|
|
new = crc32(new, rdbuf, n);
|
|
len -= n;
|
|
off += n;
|
|
}
|
|
|
|
if (crc == new) {
|
|
gd->env_valid = ENV_VALID;
|
|
} else {
|
|
gd->env_valid = ENV_INVALID;
|
|
}
|
|
#endif /* CONFIG_ENV_OFFSET_REDUND */
|
|
|
|
off = CONFIG_ENV_OFFSET;
|
|
#ifdef CONFIG_ENV_OFFSET_REDUND
|
|
if (gd->env_valid == ENV_REDUND)
|
|
off = CONFIG_ENV_OFFSET_REDUND;
|
|
#endif
|
|
|
|
eeprom_bus_read(CONFIG_SYS_DEF_EEPROM_ADDR,
|
|
off, (uchar *)buf_env, CONFIG_ENV_SIZE);
|
|
|
|
return env_import(buf_env, 1);
|
|
}
|
|
|
|
static int env_eeprom_save(void)
|
|
{
|
|
env_t env_new;
|
|
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;
|
|
#endif
|
|
|
|
rc = env_export(&env_new);
|
|
if (rc)
|
|
return rc;
|
|
|
|
#ifdef CONFIG_ENV_OFFSET_REDUND
|
|
if (gd->env_valid == ENV_VALID) {
|
|
off = CONFIG_ENV_OFFSET_REDUND;
|
|
off_red = CONFIG_ENV_OFFSET;
|
|
}
|
|
|
|
env_new.flags = ACTIVE_FLAG;
|
|
#endif
|
|
|
|
rc = eeprom_bus_write(CONFIG_SYS_DEF_EEPROM_ADDR,
|
|
off, (uchar *)&env_new, 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 == ENV_VALID)
|
|
gd->env_valid = ENV_REDUND;
|
|
else
|
|
gd->env_valid = ENV_VALID;
|
|
}
|
|
#endif
|
|
return rc;
|
|
}
|
|
|
|
U_BOOT_ENV_LOCATION(eeprom) = {
|
|
.location = ENVL_EEPROM,
|
|
ENV_NAME("EEPROM")
|
|
.load = env_eeprom_load,
|
|
.save = env_save_ptr(env_eeprom_save),
|
|
};
|