]> git.ipfire.org Git - people/ms/u-boot.git/blame - env/eeprom.c
imx: hab: Check if CSF contains deprecated commands
[people/ms/u-boot.git] / env / eeprom.c
CommitLineData
0bc4a1ac 1/*
ea882baf 2 * (C) Copyright 2000-2010
0bc4a1ac
WD
3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4 *
5 * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
6 * Andreas Heppel <aheppel@sysgo.de>
ea882baf 7 *
3765b3e7 8 * SPDX-License-Identifier: GPL-2.0+
0bc4a1ac
WD
9 */
10
11#include <common.h>
0bc4a1ac
WD
12#include <command.h>
13#include <environment.h>
0bc4a1ac 14#include <linux/stddef.h>
548738b4
HS
15#if defined(CONFIG_I2C_ENV_EEPROM_BUS)
16#include <i2c.h>
17#endif
ea882baf
WD
18#include <search.h>
19#include <errno.h>
20#include <linux/compiler.h> /* for BUG_ON */
0bc4a1ac 21
d87080b7
WD
22DECLARE_GLOBAL_DATA_PTR;
23
ea882baf 24static int eeprom_bus_read(unsigned dev_addr, unsigned offset,
dd2a233c 25 uchar *buffer, unsigned cnt)
548738b4
HS
26{
27 int rcode;
28#if defined(CONFIG_I2C_ENV_EEPROM_BUS)
29 int old_bus = i2c_get_bus_num();
30
3f4978c7
HS
31 if (old_bus != CONFIG_I2C_ENV_EEPROM_BUS)
32 i2c_set_bus_num(CONFIG_I2C_ENV_EEPROM_BUS);
548738b4
HS
33#endif
34
dd2a233c 35 rcode = eeprom_read(dev_addr, offset, buffer, cnt);
ea882baf 36
548738b4 37#if defined(CONFIG_I2C_ENV_EEPROM_BUS)
6d001e7d 38 i2c_set_bus_num(old_bus);
548738b4 39#endif
9a2accb4 40
548738b4
HS
41 return rcode;
42}
43
ea882baf 44static int eeprom_bus_write(unsigned dev_addr, unsigned offset,
dd2a233c 45 uchar *buffer, unsigned cnt)
548738b4
HS
46{
47 int rcode;
48#if defined(CONFIG_I2C_ENV_EEPROM_BUS)
49 int old_bus = i2c_get_bus_num();
50
3f4978c7
HS
51 if (old_bus != CONFIG_I2C_ENV_EEPROM_BUS)
52 i2c_set_bus_num(CONFIG_I2C_ENV_EEPROM_BUS);
548738b4 53#endif
9a2accb4 54
ea882baf 55 rcode = eeprom_write(dev_addr, offset, buffer, cnt);
9a2accb4 56
548738b4
HS
57#if defined(CONFIG_I2C_ENV_EEPROM_BUS)
58 i2c_set_bus_num(old_bus);
59#endif
6d001e7d 60
548738b4
HS
61 return rcode;
62}
0bc4a1ac 63
b2cdef48
GS
64/** Call this function from overridden env_get_char_spec() if you need
65 * this functionality.
66 */
67int env_eeprom_get_char(int index)
0bc4a1ac
WD
68{
69 uchar c;
dd2a233c 70 unsigned int off = CONFIG_ENV_OFFSET;
ea882baf 71
1567b596 72#ifdef CONFIG_ENV_OFFSET_REDUND
203e94f6 73 if (gd->env_valid == ENV_REDUND)
1567b596
HS
74 off = CONFIG_ENV_OFFSET_REDUND;
75#endif
ea882baf 76 eeprom_bus_read(CONFIG_SYS_DEF_EEPROM_ADDR,
dd2a233c 77 off + index + offsetof(env_t, data), &c, 1);
0bc4a1ac 78
dd2a233c 79 return c;
0bc4a1ac
WD
80}
81
c5951991 82static int env_eeprom_load(void)
0bc4a1ac 83{
e3cc5bc5 84 char buf_env[CONFIG_ENV_SIZE];
1567b596 85 unsigned int off = CONFIG_ENV_OFFSET;
ea882baf 86
1567b596 87#ifdef CONFIG_ENV_OFFSET_REDUND
dd2a233c 88 ulong len, crc[2], crc_tmp;
e3cc5bc5
LD
89 unsigned int off_env[2];
90 uchar rdbuf[64], flags[2];
dd2a233c 91 int i, crc_ok[2] = {0, 0};
1567b596 92
354e3ed7 93 eeprom_init(-1); /* prepare for EEPROM read/write */
1567b596
HS
94
95 off_env[0] = CONFIG_ENV_OFFSET;
96 off_env[1] = CONFIG_ENV_OFFSET_REDUND;
97
98 for (i = 0; i < 2; i++) {
99 /* read CRC */
ea882baf 100 eeprom_bus_read(CONFIG_SYS_DEF_EEPROM_ADDR,
dd2a233c
IG
101 off_env[i] + offsetof(env_t, crc),
102 (uchar *)&crc[i], sizeof(ulong));
1567b596 103 /* read FLAGS */
ea882baf 104 eeprom_bus_read(CONFIG_SYS_DEF_EEPROM_ADDR,
dd2a233c
IG
105 off_env[i] + offsetof(env_t, flags),
106 (uchar *)&flags[i], sizeof(uchar));
1567b596 107
ea882baf 108 crc_tmp = 0;
1567b596 109 len = ENV_SIZE;
dd2a233c 110 off = off_env[i] + offsetof(env_t, data);
1567b596 111 while (len > 0) {
e3cc5bc5 112 int n = (len > sizeof(rdbuf)) ? sizeof(rdbuf) : len;
1567b596 113
ea882baf 114 eeprom_bus_read(CONFIG_SYS_DEF_EEPROM_ADDR, off,
e3cc5bc5 115 rdbuf, n);
1567b596 116
e3cc5bc5 117 crc_tmp = crc32(crc_tmp, rdbuf, n);
1567b596
HS
118 len -= n;
119 off += n;
120 }
dd2a233c 121
1567b596
HS
122 if (crc_tmp == crc[i])
123 crc_ok[i] = 1;
124 }
125
126 if (!crc_ok[0] && !crc_ok[1]) {
dd2a233c 127 gd->env_addr = 0;
2d7cb5b4 128 gd->env_valid = ENV_INVALID;
1567b596 129 } else if (crc_ok[0] && !crc_ok[1]) {
203e94f6 130 gd->env_valid = ENV_VALID;
dd2a233c 131 } else if (!crc_ok[0] && crc_ok[1]) {
203e94f6 132 gd->env_valid = ENV_REDUND;
1567b596
HS
133 } else {
134 /* both ok - check serial */
135 if (flags[0] == ACTIVE_FLAG && flags[1] == OBSOLETE_FLAG)
203e94f6 136 gd->env_valid = ENV_VALID;
1567b596 137 else if (flags[0] == OBSOLETE_FLAG && flags[1] == ACTIVE_FLAG)
203e94f6 138 gd->env_valid = ENV_REDUND;
1567b596 139 else if (flags[0] == 0xFF && flags[1] == 0)
203e94f6 140 gd->env_valid = ENV_REDUND;
dd2a233c 141 else if (flags[1] == 0xFF && flags[0] == 0)
203e94f6 142 gd->env_valid = ENV_VALID;
1567b596 143 else /* flags are equal - almost impossible */
203e94f6 144 gd->env_valid = ENV_VALID;
1567b596
HS
145 }
146
e3cc5bc5 147#else /* CONFIG_ENV_OFFSET_REDUND */
0bc4a1ac 148 ulong crc, len, new;
e3cc5bc5 149 uchar rdbuf[64];
0bc4a1ac 150
354e3ed7 151 eeprom_init(-1); /* prepare for EEPROM read/write */
0bc4a1ac
WD
152
153 /* read old CRC */
ea882baf 154 eeprom_bus_read(CONFIG_SYS_DEF_EEPROM_ADDR,
dd2a233c
IG
155 CONFIG_ENV_OFFSET + offsetof(env_t, crc),
156 (uchar *)&crc, sizeof(ulong));
0bc4a1ac
WD
157
158 new = 0;
159 len = ENV_SIZE;
dd2a233c 160 off = offsetof(env_t, data);
0bc4a1ac 161 while (len > 0) {
e3cc5bc5 162 int n = (len > sizeof(rdbuf)) ? sizeof(rdbuf) : len;
0bc4a1ac 163
ea882baf 164 eeprom_bus_read(CONFIG_SYS_DEF_EEPROM_ADDR,
e3cc5bc5
LD
165 CONFIG_ENV_OFFSET + off, rdbuf, n);
166 new = crc32(new, rdbuf, n);
0bc4a1ac
WD
167 len -= n;
168 off += n;
169 }
170
171 if (crc == new) {
2d7cb5b4 172 gd->env_valid = ENV_VALID;
0bc4a1ac 173 } else {
2d7cb5b4 174 gd->env_valid = ENV_INVALID;
0bc4a1ac 175 }
e3cc5bc5
LD
176#endif /* CONFIG_ENV_OFFSET_REDUND */
177
178 off = CONFIG_ENV_OFFSET;
179#ifdef CONFIG_ENV_OFFSET_REDUND
203e94f6 180 if (gd->env_valid == ENV_REDUND)
e3cc5bc5
LD
181 off = CONFIG_ENV_OFFSET_REDUND;
182#endif
183
184 eeprom_bus_read(CONFIG_SYS_DEF_EEPROM_ADDR,
185 off, (uchar *)buf_env, CONFIG_ENV_SIZE);
186
2166ebf7 187 return env_import(buf_env, 1);
e3cc5bc5
LD
188}
189
e5bce247 190static int env_eeprom_save(void)
e3cc5bc5
LD
191{
192 env_t env_new;
193 int rc;
194 unsigned int off = CONFIG_ENV_OFFSET;
195#ifdef CONFIG_ENV_OFFSET_REDUND
196 unsigned int off_red = CONFIG_ENV_OFFSET_REDUND;
197 char flag_obsolete = OBSOLETE_FLAG;
198#endif
199
e3cc5bc5
LD
200 rc = env_export(&env_new);
201 if (rc)
202 return rc;
203
204#ifdef CONFIG_ENV_OFFSET_REDUND
203e94f6 205 if (gd->env_valid == ENV_VALID) {
e3cc5bc5
LD
206 off = CONFIG_ENV_OFFSET_REDUND;
207 off_red = CONFIG_ENV_OFFSET;
208 }
209
210 env_new.flags = ACTIVE_FLAG;
211#endif
212
213 rc = eeprom_bus_write(CONFIG_SYS_DEF_EEPROM_ADDR,
214 off, (uchar *)&env_new, CONFIG_ENV_SIZE);
215
216#ifdef CONFIG_ENV_OFFSET_REDUND
217 if (rc == 0) {
218 eeprom_bus_write(CONFIG_SYS_DEF_EEPROM_ADDR,
219 off_red + offsetof(env_t, flags),
220 (uchar *)&flag_obsolete, 1);
221
203e94f6
SG
222 if (gd->env_valid == ENV_VALID)
223 gd->env_valid = ENV_REDUND;
e3cc5bc5 224 else
203e94f6 225 gd->env_valid = ENV_VALID;
e3cc5bc5
LD
226 }
227#endif
228 return rc;
229}
230
4415f1d1
SG
231U_BOOT_ENV_LOCATION(eeprom) = {
232 .location = ENVL_EEPROM,
ac358beb 233 ENV_NAME("EEPROM")
e5bce247
SG
234 .load = env_eeprom_load,
235 .save = env_save_ptr(env_eeprom_save),
4415f1d1 236};