Blame view

common/env_sf.c 7.36 KB
8c66497e0   Haavard Skinnemoen   Add support for e...
1
  /*
ea882baf9   Wolfgang Denk   New implementatio...
2
   * (C) Copyright 2000-2010
8c66497e0   Haavard Skinnemoen   Add support for e...
3
4
5
6
7
8
9
   * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
   *
   * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
   * Andreas Heppel <aheppel@sysgo.de>
   *
   * (C) Copyright 2008 Atmel Corporation
   *
402ba1e3a   Jagannadha Sutradharudu Teki   cmd_sf|env_sf: Fi...
10
   * SPDX-License-Identifier:	GPL-2.0+
8c66497e0   Haavard Skinnemoen   Add support for e...
11
12
   */
  #include <common.h>
8c66497e0   Haavard Skinnemoen   Add support for e...
13
  #include <environment.h>
5b3375ac8   Mike Frysinger   env_sf: support e...
14
  #include <malloc.h>
8c66497e0   Haavard Skinnemoen   Add support for e...
15
  #include <spi_flash.h>
ea882baf9   Wolfgang Denk   New implementatio...
16
17
  #include <search.h>
  #include <errno.h>
8c66497e0   Haavard Skinnemoen   Add support for e...
18

0e8d15866   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ENV ma...
19
20
  #ifndef CONFIG_ENV_SPI_BUS
  # define CONFIG_ENV_SPI_BUS	0
8c66497e0   Haavard Skinnemoen   Add support for e...
21
  #endif
0e8d15866   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ENV ma...
22
  #ifndef CONFIG_ENV_SPI_CS
eb58a7fc7   Igor Grinberg   env: clean env_sf...
23
  # define CONFIG_ENV_SPI_CS	0
8c66497e0   Haavard Skinnemoen   Add support for e...
24
  #endif
0e8d15866   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ENV ma...
25
26
  #ifndef CONFIG_ENV_SPI_MAX_HZ
  # define CONFIG_ENV_SPI_MAX_HZ	1000000
8c66497e0   Haavard Skinnemoen   Add support for e...
27
  #endif
0e8d15866   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ENV ma...
28
29
  #ifndef CONFIG_ENV_SPI_MODE
  # define CONFIG_ENV_SPI_MODE	SPI_MODE_3
8c66497e0   Haavard Skinnemoen   Add support for e...
30
  #endif
7319bcaf8   Wolfgang Wegner   add redundant env...
31
  #ifdef CONFIG_ENV_OFFSET_REDUND
eb58a7fc7   Igor Grinberg   env: clean env_sf...
32
33
  static ulong env_offset		= CONFIG_ENV_OFFSET;
  static ulong env_new_offset	= CONFIG_ENV_OFFSET_REDUND;
7319bcaf8   Wolfgang Wegner   add redundant env...
34

eb58a7fc7   Igor Grinberg   env: clean env_sf...
35
36
  #define ACTIVE_FLAG	1
  #define OBSOLETE_FLAG	0
a3110f01c   Stefano Babic   env_sf: updated t...
37
  #endif /* CONFIG_ENV_OFFSET_REDUND */
7319bcaf8   Wolfgang Wegner   add redundant env...
38

8c66497e0   Haavard Skinnemoen   Add support for e...
39
  DECLARE_GLOBAL_DATA_PTR;
eb58a7fc7   Igor Grinberg   env: clean env_sf...
40
  char *env_name_spec = "SPI Flash";
8c66497e0   Haavard Skinnemoen   Add support for e...
41
42
  
  static struct spi_flash *env_flash;
7319bcaf8   Wolfgang Wegner   add redundant env...
43
  #if defined(CONFIG_ENV_OFFSET_REDUND)
7319bcaf8   Wolfgang Wegner   add redundant env...
44
45
  int saveenv(void)
  {
cd0f4fa1c   Tom Rini   Revert "env: fix ...
46
  	env_t	env_new;
ea882baf9   Wolfgang Denk   New implementatio...
47
  	ssize_t	len;
eb58a7fc7   Igor Grinberg   env: clean env_sf...
48
49
  	char	*res, *saved_buffer = NULL, flag = OBSOLETE_FLAG;
  	u32	saved_size, saved_offset, sector = 1;
ea882baf9   Wolfgang Denk   New implementatio...
50
  	int	ret;
7319bcaf8   Wolfgang Wegner   add redundant env...
51
52
  
  	if (!env_flash) {
a3110f01c   Stefano Babic   env_sf: updated t...
53
54
55
56
57
58
59
  		env_flash = spi_flash_probe(CONFIG_ENV_SPI_BUS,
  			CONFIG_ENV_SPI_CS,
  			CONFIG_ENV_SPI_MAX_HZ, CONFIG_ENV_SPI_MODE);
  		if (!env_flash) {
  			set_default_env("!spi_flash_probe() failed");
  			return 1;
  		}
7319bcaf8   Wolfgang Wegner   add redundant env...
60
  	}
cd0f4fa1c   Tom Rini   Revert "env: fix ...
61
  	res = (char *)&env_new.data;
be11235ab   Joe Hershberger   env: Hide '.' var...
62
  	len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
ea882baf9   Wolfgang Denk   New implementatio...
63
64
65
66
67
  	if (len < 0) {
  		error("Cannot export environment: errno = %d
  ", errno);
  		return 1;
  	}
cd0f4fa1c   Tom Rini   Revert "env: fix ...
68
69
  	env_new.crc	= crc32(0, env_new.data, ENV_SIZE);
  	env_new.flags	= ACTIVE_FLAG;
ea882baf9   Wolfgang Denk   New implementatio...
70

a3110f01c   Stefano Babic   env_sf: updated t...
71
72
73
74
75
76
77
  	if (gd->env_valid == 1) {
  		env_new_offset = CONFIG_ENV_OFFSET_REDUND;
  		env_offset = CONFIG_ENV_OFFSET;
  	} else {
  		env_new_offset = CONFIG_ENV_OFFSET;
  		env_offset = CONFIG_ENV_OFFSET_REDUND;
  	}
7319bcaf8   Wolfgang Wegner   add redundant env...
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
  	/* Is the sector larger than the env (i.e. embedded) */
  	if (CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE) {
  		saved_size = CONFIG_ENV_SECT_SIZE - CONFIG_ENV_SIZE;
  		saved_offset = env_new_offset + CONFIG_ENV_SIZE;
  		saved_buffer = malloc(saved_size);
  		if (!saved_buffer) {
  			ret = 1;
  			goto done;
  		}
  		ret = spi_flash_read(env_flash, saved_offset,
  					saved_size, saved_buffer);
  		if (ret)
  			goto done;
  	}
  
  	if (CONFIG_ENV_SIZE > CONFIG_ENV_SECT_SIZE) {
  		sector = CONFIG_ENV_SIZE / CONFIG_ENV_SECT_SIZE;
  		if (CONFIG_ENV_SIZE % CONFIG_ENV_SECT_SIZE)
  			sector++;
  	}
  
  	puts("Erasing SPI flash...");
  	ret = spi_flash_erase(env_flash, env_new_offset,
  				sector * CONFIG_ENV_SECT_SIZE);
  	if (ret)
  		goto done;
  
  	puts("Writing to SPI flash...");
7319bcaf8   Wolfgang Wegner   add redundant env...
106

a3110f01c   Stefano Babic   env_sf: updated t...
107
  	ret = spi_flash_write(env_flash, env_new_offset,
cd0f4fa1c   Tom Rini   Revert "env: fix ...
108
  		CONFIG_ENV_SIZE, &env_new);
7319bcaf8   Wolfgang Wegner   add redundant env...
109
110
111
112
113
114
115
116
117
  	if (ret)
  		goto done;
  
  	if (CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE) {
  		ret = spi_flash_write(env_flash, saved_offset,
  					saved_size, saved_buffer);
  		if (ret)
  			goto done;
  	}
eb58a7fc7   Igor Grinberg   env: clean env_sf...
118
  	ret = spi_flash_write(env_flash, env_offset + offsetof(env_t, flags),
cd0f4fa1c   Tom Rini   Revert "env: fix ...
119
  				sizeof(env_new.flags), &flag);
a3110f01c   Stefano Babic   env_sf: updated t...
120
121
  	if (ret)
  		goto done;
7319bcaf8   Wolfgang Wegner   add redundant env...
122

7319bcaf8   Wolfgang Wegner   add redundant env...
123
124
  	puts("done
  ");
eb58a7fc7   Igor Grinberg   env: clean env_sf...
125
  	gd->env_valid = gd->env_valid == 2 ? 1 : 2;
a3110f01c   Stefano Babic   env_sf: updated t...
126

2dc55d9ed   thomas.langer@lantiq.com   fix redundant env...
127
128
  	printf("Valid environment: %d
  ", (int)gd->env_valid);
a3110f01c   Stefano Babic   env_sf: updated t...
129

7319bcaf8   Wolfgang Wegner   add redundant env...
130
131
132
   done:
  	if (saved_buffer)
  		free(saved_buffer);
eb58a7fc7   Igor Grinberg   env: clean env_sf...
133

7319bcaf8   Wolfgang Wegner   add redundant env...
134
135
136
137
138
139
140
141
142
  	return ret;
  }
  
  void env_relocate_spec(void)
  {
  	int ret;
  	int crc1_ok = 0, crc2_ok = 0;
  	env_t *tmp_env1 = NULL;
  	env_t *tmp_env2 = NULL;
a3110f01c   Stefano Babic   env_sf: updated t...
143
  	env_t *ep = NULL;
7319bcaf8   Wolfgang Wegner   add redundant env...
144
145
  
  	tmp_env1 = (env_t *)malloc(CONFIG_ENV_SIZE);
7319bcaf8   Wolfgang Wegner   add redundant env...
146
  	tmp_env2 = (env_t *)malloc(CONFIG_ENV_SIZE);
ea882baf9   Wolfgang Denk   New implementatio...
147
148
  
  	if (!tmp_env1 || !tmp_env2) {
ea882baf9   Wolfgang Denk   New implementatio...
149
  		set_default_env("!malloc() failed");
2dc55d9ed   thomas.langer@lantiq.com   fix redundant env...
150
  		goto out;
7319bcaf8   Wolfgang Wegner   add redundant env...
151
152
153
154
  	}
  
  	env_flash = spi_flash_probe(CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS,
  			CONFIG_ENV_SPI_MAX_HZ, CONFIG_ENV_SPI_MODE);
ea882baf9   Wolfgang Denk   New implementatio...
155
156
  	if (!env_flash) {
  		set_default_env("!spi_flash_probe() failed");
2dc55d9ed   thomas.langer@lantiq.com   fix redundant env...
157
  		goto out;
ea882baf9   Wolfgang Denk   New implementatio...
158
  	}
7319bcaf8   Wolfgang Wegner   add redundant env...
159
160
161
  
  	ret = spi_flash_read(env_flash, CONFIG_ENV_OFFSET,
  				CONFIG_ENV_SIZE, tmp_env1);
ea882baf9   Wolfgang Denk   New implementatio...
162
163
  	if (ret) {
  		set_default_env("!spi_flash_read() failed");
7319bcaf8   Wolfgang Wegner   add redundant env...
164
  		goto err_read;
ea882baf9   Wolfgang Denk   New implementatio...
165
  	}
7319bcaf8   Wolfgang Wegner   add redundant env...
166
167
168
  
  	if (crc32(0, tmp_env1->data, ENV_SIZE) == tmp_env1->crc)
  		crc1_ok = 1;
7319bcaf8   Wolfgang Wegner   add redundant env...
169
170
171
172
173
174
  
  	ret = spi_flash_read(env_flash, CONFIG_ENV_OFFSET_REDUND,
  				CONFIG_ENV_SIZE, tmp_env2);
  	if (!ret) {
  		if (crc32(0, tmp_env2->data, ENV_SIZE) == tmp_env2->crc)
  			crc2_ok = 1;
7319bcaf8   Wolfgang Wegner   add redundant env...
175
  	}
a3110f01c   Stefano Babic   env_sf: updated t...
176
  	if (!crc1_ok && !crc2_ok) {
a3110f01c   Stefano Babic   env_sf: updated t...
177
  		set_default_env("!bad CRC");
2dc55d9ed   thomas.langer@lantiq.com   fix redundant env...
178
  		goto err_read;
a3110f01c   Stefano Babic   env_sf: updated t...
179
  	} else if (crc1_ok && !crc2_ok) {
7319bcaf8   Wolfgang Wegner   add redundant env...
180
  		gd->env_valid = 1;
7319bcaf8   Wolfgang Wegner   add redundant env...
181
  	} else if (!crc1_ok && crc2_ok) {
2dc55d9ed   thomas.langer@lantiq.com   fix redundant env...
182
183
184
  		gd->env_valid = 2;
  	} else if (tmp_env1->flags == ACTIVE_FLAG &&
  		   tmp_env2->flags == OBSOLETE_FLAG) {
7319bcaf8   Wolfgang Wegner   add redundant env...
185
  		gd->env_valid = 1;
2dc55d9ed   thomas.langer@lantiq.com   fix redundant env...
186
187
  	} else if (tmp_env1->flags == OBSOLETE_FLAG &&
  		   tmp_env2->flags == ACTIVE_FLAG) {
a3110f01c   Stefano Babic   env_sf: updated t...
188
  		gd->env_valid = 2;
2dc55d9ed   thomas.langer@lantiq.com   fix redundant env...
189
  	} else if (tmp_env1->flags == tmp_env2->flags) {
7319bcaf8   Wolfgang Wegner   add redundant env...
190
  		gd->env_valid = 2;
2dc55d9ed   thomas.langer@lantiq.com   fix redundant env...
191
  	} else if (tmp_env1->flags == 0xFF) {
7319bcaf8   Wolfgang Wegner   add redundant env...
192
  		gd->env_valid = 2;
7319bcaf8   Wolfgang Wegner   add redundant env...
193
194
195
196
197
198
  	} else {
  		/*
  		 * this differs from code in env_flash.c, but I think a sane
  		 * default path is desirable.
  		 */
  		gd->env_valid = 2;
7319bcaf8   Wolfgang Wegner   add redundant env...
199
  	}
ea882baf9   Wolfgang Denk   New implementatio...
200

a3110f01c   Stefano Babic   env_sf: updated t...
201
202
203
204
205
206
207
208
209
210
  	if (gd->env_valid == 1)
  		ep = tmp_env1;
  	else
  		ep = tmp_env2;
  
  	ret = env_import((char *)ep, 0);
  	if (!ret) {
  		error("Cannot import environment: errno = %d
  ", errno);
  		set_default_env("env_import failed");
7319bcaf8   Wolfgang Wegner   add redundant env...
211
  	}
7319bcaf8   Wolfgang Wegner   add redundant env...
212
213
214
215
  
  err_read:
  	spi_flash_free(env_flash);
  	env_flash = NULL;
7319bcaf8   Wolfgang Wegner   add redundant env...
216
  out:
ea882baf9   Wolfgang Denk   New implementatio...
217
218
  	free(tmp_env1);
  	free(tmp_env2);
7319bcaf8   Wolfgang Wegner   add redundant env...
219
220
  }
  #else
8c66497e0   Haavard Skinnemoen   Add support for e...
221
222
  int saveenv(void)
  {
eb58a7fc7   Igor Grinberg   env: clean env_sf...
223
224
225
  	u32	saved_size, saved_offset, sector = 1;
  	char	*res, *saved_buffer = NULL;
  	int	ret = 1;
cd0f4fa1c   Tom Rini   Revert "env: fix ...
226
  	env_t	env_new;
a3110f01c   Stefano Babic   env_sf: updated t...
227
  	ssize_t	len;
07efc9e32   TsiChung Liew   Change CFG_ENV_SI...
228

8c66497e0   Haavard Skinnemoen   Add support for e...
229
  	if (!env_flash) {
a3110f01c   Stefano Babic   env_sf: updated t...
230
231
232
233
234
235
236
  		env_flash = spi_flash_probe(CONFIG_ENV_SPI_BUS,
  			CONFIG_ENV_SPI_CS,
  			CONFIG_ENV_SPI_MAX_HZ, CONFIG_ENV_SPI_MODE);
  		if (!env_flash) {
  			set_default_env("!spi_flash_probe() failed");
  			return 1;
  		}
8c66497e0   Haavard Skinnemoen   Add support for e...
237
  	}
5b3375ac8   Mike Frysinger   env_sf: support e...
238
239
240
241
242
  	/* Is the sector larger than the env (i.e. embedded) */
  	if (CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE) {
  		saved_size = CONFIG_ENV_SECT_SIZE - CONFIG_ENV_SIZE;
  		saved_offset = CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE;
  		saved_buffer = malloc(saved_size);
eb58a7fc7   Igor Grinberg   env: clean env_sf...
243
  		if (!saved_buffer)
5b3375ac8   Mike Frysinger   env_sf: support e...
244
  			goto done;
eb58a7fc7   Igor Grinberg   env: clean env_sf...
245

a3110f01c   Stefano Babic   env_sf: updated t...
246
247
  		ret = spi_flash_read(env_flash, saved_offset,
  			saved_size, saved_buffer);
5b3375ac8   Mike Frysinger   env_sf: support e...
248
249
250
  		if (ret)
  			goto done;
  	}
0e8d15866   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ENV ma...
251
252
253
  	if (CONFIG_ENV_SIZE > CONFIG_ENV_SECT_SIZE) {
  		sector = CONFIG_ENV_SIZE / CONFIG_ENV_SECT_SIZE;
  		if (CONFIG_ENV_SIZE % CONFIG_ENV_SECT_SIZE)
07efc9e32   TsiChung Liew   Change CFG_ENV_SI...
254
255
  			sector++;
  	}
cd0f4fa1c   Tom Rini   Revert "env: fix ...
256
  	res = (char *)&env_new.data;
be11235ab   Joe Hershberger   env: Hide '.' var...
257
  	len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
a3110f01c   Stefano Babic   env_sf: updated t...
258
259
260
261
262
  	if (len < 0) {
  		error("Cannot export environment: errno = %d
  ", errno);
  		goto done;
  	}
cd0f4fa1c   Tom Rini   Revert "env: fix ...
263
  	env_new.crc = crc32(0, env_new.data, ENV_SIZE);
a3110f01c   Stefano Babic   env_sf: updated t...
264

8c66497e0   Haavard Skinnemoen   Add support for e...
265
  	puts("Erasing SPI flash...");
a3110f01c   Stefano Babic   env_sf: updated t...
266
267
  	ret = spi_flash_erase(env_flash, CONFIG_ENV_OFFSET,
  		sector * CONFIG_ENV_SECT_SIZE);
5b3375ac8   Mike Frysinger   env_sf: support e...
268
269
  	if (ret)
  		goto done;
8c66497e0   Haavard Skinnemoen   Add support for e...
270
271
  
  	puts("Writing to SPI flash...");
a3110f01c   Stefano Babic   env_sf: updated t...
272
  	ret = spi_flash_write(env_flash, CONFIG_ENV_OFFSET,
cd0f4fa1c   Tom Rini   Revert "env: fix ...
273
  		CONFIG_ENV_SIZE, &env_new);
5b3375ac8   Mike Frysinger   env_sf: support e...
274
275
  	if (ret)
  		goto done;
8c66497e0   Haavard Skinnemoen   Add support for e...
276

5b3375ac8   Mike Frysinger   env_sf: support e...
277
  	if (CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE) {
a3110f01c   Stefano Babic   env_sf: updated t...
278
279
  		ret = spi_flash_write(env_flash, saved_offset,
  			saved_size, saved_buffer);
5b3375ac8   Mike Frysinger   env_sf: support e...
280
281
282
283
284
  		if (ret)
  			goto done;
  	}
  
  	ret = 0;
8c66497e0   Haavard Skinnemoen   Add support for e...
285
286
  	puts("done
  ");
5b3375ac8   Mike Frysinger   env_sf: support e...
287
288
289
290
  
   done:
  	if (saved_buffer)
  		free(saved_buffer);
eb58a7fc7   Igor Grinberg   env: clean env_sf...
291

5b3375ac8   Mike Frysinger   env_sf: support e...
292
  	return ret;
8c66497e0   Haavard Skinnemoen   Add support for e...
293
294
295
296
  }
  
  void env_relocate_spec(void)
  {
cd0f4fa1c   Tom Rini   Revert "env: fix ...
297
  	char buf[CONFIG_ENV_SIZE];
8c66497e0   Haavard Skinnemoen   Add support for e...
298
  	int ret;
0e8d15866   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ENV ma...
299
300
  	env_flash = spi_flash_probe(CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS,
  			CONFIG_ENV_SPI_MAX_HZ, CONFIG_ENV_SPI_MODE);
ea882baf9   Wolfgang Denk   New implementatio...
301
302
303
304
  	if (!env_flash) {
  		set_default_env("!spi_flash_probe() failed");
  		return;
  	}
8c66497e0   Haavard Skinnemoen   Add support for e...
305

ea882baf9   Wolfgang Denk   New implementatio...
306
307
308
309
310
311
  	ret = spi_flash_read(env_flash,
  		CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE, buf);
  	if (ret) {
  		set_default_env("!spi_flash_read() failed");
  		goto out;
  	}
8c66497e0   Haavard Skinnemoen   Add support for e...
312

ea882baf9   Wolfgang Denk   New implementatio...
313
  	ret = env_import(buf, 1);
ea882baf9   Wolfgang Denk   New implementatio...
314
315
316
  	if (ret)
  		gd->env_valid = 1;
  out:
8c66497e0   Haavard Skinnemoen   Add support for e...
317
318
  	spi_flash_free(env_flash);
  	env_flash = NULL;
8c66497e0   Haavard Skinnemoen   Add support for e...
319
  }
7319bcaf8   Wolfgang Wegner   add redundant env...
320
  #endif
8c66497e0   Haavard Skinnemoen   Add support for e...
321
322
323
324
325
326
327
328
329
  
  int env_init(void)
  {
  	/* SPI flash isn't usable before relocation */
  	gd->env_addr = (ulong)&default_environment[0];
  	gd->env_valid = 1;
  
  	return 0;
  }