Commit 1567b596d9f4a7ff49ebdca29e15a33777dfd670
Committed by
Wolfgang Denk
1 parent
548738b4d4
Exists in
master
and in
54 other branches
env, eeprom: add redundant environment support
Add redundant environment support for environment lying on a EEPROM. Tested on uppcoming suen3 support Signed-off-by: Andreas Huber <andreas.huber@keymile.com>
Showing 1 changed file with 127 additions and 4 deletions Side-by-side Diff
common/env_eeprom.c
... | ... | @@ -32,6 +32,11 @@ |
32 | 32 | #include <i2c.h> |
33 | 33 | #endif |
34 | 34 | |
35 | +#ifdef CONFIG_ENV_OFFSET_REDUND | |
36 | +#define ACTIVE_FLAG 1 | |
37 | +#define OBSOLETE_FLAG 0 | |
38 | +#endif | |
39 | + | |
35 | 40 | DECLARE_GLOBAL_DATA_PTR; |
36 | 41 | |
37 | 42 | env_t *env_ptr = NULL; |
38 | 43 | |
... | ... | @@ -93,9 +98,15 @@ |
93 | 98 | uchar env_get_char_spec (int index) |
94 | 99 | { |
95 | 100 | uchar c; |
101 | + unsigned int off; | |
102 | + off = CONFIG_ENV_OFFSET; | |
103 | +#ifdef CONFIG_ENV_OFFSET_REDUND | |
104 | + if (gd->env_valid == 2) | |
105 | + off = CONFIG_ENV_OFFSET_REDUND; | |
106 | +#endif | |
96 | 107 | |
97 | 108 | eeprom_bus_read (CONFIG_SYS_DEF_EEPROM_ADDR, |
98 | - CONFIG_ENV_OFFSET+index+offsetof(env_t,data), | |
109 | + off + index + offsetof(env_t,data), | |
99 | 110 | &c, 1); |
100 | 111 | |
101 | 112 | return (c); |
102 | 113 | |
103 | 114 | |
104 | 115 | |
... | ... | @@ -103,18 +114,52 @@ |
103 | 114 | |
104 | 115 | void env_relocate_spec (void) |
105 | 116 | { |
117 | + unsigned int off = CONFIG_ENV_OFFSET; | |
118 | +#ifdef CONFIG_ENV_OFFSET_REDUND | |
119 | + if (gd->env_valid == 2) | |
120 | + off = CONFIG_ENV_OFFSET_REDUND; | |
121 | +#endif | |
106 | 122 | eeprom_bus_read (CONFIG_SYS_DEF_EEPROM_ADDR, |
107 | - CONFIG_ENV_OFFSET, | |
123 | + off, | |
108 | 124 | (uchar*)env_ptr, |
109 | 125 | CONFIG_ENV_SIZE); |
110 | 126 | } |
111 | 127 | |
112 | 128 | int saveenv(void) |
113 | 129 | { |
114 | - return eeprom_bus_write (CONFIG_SYS_DEF_EEPROM_ADDR, | |
115 | - CONFIG_ENV_OFFSET, | |
130 | + int rc; | |
131 | + unsigned int off = CONFIG_ENV_OFFSET; | |
132 | +#ifdef CONFIG_ENV_OFFSET_REDUND | |
133 | + unsigned int off_red = CONFIG_ENV_OFFSET_REDUND; | |
134 | + char flag_obsolete = OBSOLETE_FLAG; | |
135 | + if (gd->env_valid == 1) { | |
136 | + off = CONFIG_ENV_OFFSET_REDUND; | |
137 | + off_red = CONFIG_ENV_OFFSET; | |
138 | + } | |
139 | + | |
140 | + env_ptr->flags = ACTIVE_FLAG; | |
141 | +#endif | |
142 | + | |
143 | + rc = eeprom_bus_write (CONFIG_SYS_DEF_EEPROM_ADDR, | |
144 | + off, | |
116 | 145 | (uchar *)env_ptr, |
117 | 146 | CONFIG_ENV_SIZE); |
147 | + | |
148 | +#ifdef CONFIG_ENV_OFFSET_REDUND | |
149 | + if (rc == 0) { | |
150 | + eeprom_bus_write (CONFIG_SYS_DEF_EEPROM_ADDR, | |
151 | + off_red + offsetof(env_t,flags), | |
152 | + (uchar *)&flag_obsolete, | |
153 | + 1); | |
154 | + if (gd->env_valid == 1) | |
155 | + gd->env_valid = 2; | |
156 | + else | |
157 | + gd->env_valid = 1; | |
158 | + | |
159 | + } | |
160 | +#endif | |
161 | + | |
162 | + return rc; | |
118 | 163 | } |
119 | 164 | |
120 | 165 | /************************************************************************ |
121 | 166 | |
... | ... | @@ -123,8 +168,84 @@ |
123 | 168 | * We are still running from ROM, so data use is limited |
124 | 169 | * Use a (moderately small) buffer on the stack |
125 | 170 | */ |
171 | + | |
172 | +#ifdef CONFIG_ENV_OFFSET_REDUND | |
126 | 173 | int env_init(void) |
127 | 174 | { |
175 | + ulong len; | |
176 | + ulong crc[2], crc_tmp; | |
177 | + unsigned int off, off_env[2]; | |
178 | + uchar buf[64]; | |
179 | + int crc_ok[2] = {0,0}; | |
180 | + unsigned char flags[2]; | |
181 | + int i; | |
182 | + | |
183 | + eeprom_init (); /* prepare for EEPROM read/write */ | |
184 | + | |
185 | + off_env[0] = CONFIG_ENV_OFFSET; | |
186 | + off_env[1] = CONFIG_ENV_OFFSET_REDUND; | |
187 | + | |
188 | + for (i = 0; i < 2; i++) { | |
189 | + /* read CRC */ | |
190 | + eeprom_bus_read (CONFIG_SYS_DEF_EEPROM_ADDR, | |
191 | + off_env[i] + offsetof(env_t,crc), | |
192 | + (uchar *)&crc[i], sizeof(ulong)); | |
193 | + /* read FLAGS */ | |
194 | + eeprom_bus_read (CONFIG_SYS_DEF_EEPROM_ADDR, | |
195 | + off_env[i] + offsetof(env_t,flags), | |
196 | + (uchar *)&flags[i], sizeof(uchar)); | |
197 | + | |
198 | + crc_tmp= 0; | |
199 | + len = ENV_SIZE; | |
200 | + off = off_env[i] + offsetof(env_t,data); | |
201 | + while (len > 0) { | |
202 | + int n = (len > sizeof(buf)) ? sizeof(buf) : len; | |
203 | + | |
204 | + eeprom_bus_read (CONFIG_SYS_DEF_EEPROM_ADDR, off, | |
205 | + buf, n); | |
206 | + | |
207 | + crc_tmp = crc32 (crc_tmp, buf, n); | |
208 | + len -= n; | |
209 | + off += n; | |
210 | + } | |
211 | + if (crc_tmp == crc[i]) | |
212 | + crc_ok[i] = 1; | |
213 | + } | |
214 | + | |
215 | + if (!crc_ok[0] && !crc_ok[1]) { | |
216 | + gd->env_addr = 0; | |
217 | + gd->env_valid = 0; | |
218 | + | |
219 | + return 0; | |
220 | + } else if (crc_ok[0] && !crc_ok[1]) { | |
221 | + gd->env_valid = 1; | |
222 | + } | |
223 | + else if (!crc_ok[0] && crc_ok[1]) { | |
224 | + gd->env_valid = 2; | |
225 | + } else { | |
226 | + /* both ok - check serial */ | |
227 | + if (flags[0] == ACTIVE_FLAG && flags[1] == OBSOLETE_FLAG) | |
228 | + gd->env_valid = 1; | |
229 | + else if (flags[0] == OBSOLETE_FLAG && flags[1] == ACTIVE_FLAG) | |
230 | + gd->env_valid = 2; | |
231 | + else if (flags[0] == 0xFF && flags[1] == 0) | |
232 | + gd->env_valid = 2; | |
233 | + else if(flags[1] == 0xFF && flags[0] == 0) | |
234 | + gd->env_valid = 1; | |
235 | + else /* flags are equal - almost impossible */ | |
236 | + gd->env_valid = 1; | |
237 | + } | |
238 | + | |
239 | + if (gd->env_valid == 2) | |
240 | + gd->env_addr = off_env[1] + offsetof(env_t,data); | |
241 | + else if (gd->env_valid == 1) | |
242 | + gd->env_addr = off_env[0] + offsetof(env_t,data); | |
243 | + | |
244 | + return (0); | |
245 | +} | |
246 | +#else | |
247 | +int env_init(void) | |
248 | +{ | |
128 | 249 | ulong crc, len, new; |
129 | 250 | unsigned off; |
130 | 251 | uchar buf[64]; |
... | ... | @@ -159,4 +280,5 @@ |
159 | 280 | |
160 | 281 | return (0); |
161 | 282 | } |
283 | +#endif |