]> Git Repo - J-u-boot.git/blame - env/sf.c
env: mmc: Add missing eMMC bootpart restoration to env erase
[J-u-boot.git] / env / sf.c
CommitLineData
83d290c5 1// SPDX-License-Identifier: GPL-2.0+
8c66497e 2/*
ea882baf 3 * (C) Copyright 2000-2010
8c66497e
HS
4 * Wolfgang Denk, DENX Software Engineering, [email protected].
5 *
6 * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
7 * Andreas Heppel <[email protected]>
8 *
9 * (C) Copyright 2008 Atmel Corporation
8c66497e
HS
10 */
11#include <common.h>
9d922450 12#include <dm.h>
0ac7d722 13#include <env.h>
f3998fdc 14#include <env_internal.h>
b79fdc76 15#include <flash.h>
5b3375ac 16#include <malloc.h>
843c9e87 17#include <spi.h>
8c66497e 18#include <spi_flash.h>
ea882baf
WD
19#include <search.h>
20#include <errno.h>
b79fdc76 21#include <uuid.h>
90526e9f 22#include <asm/cache.h>
401d1c4f 23#include <asm/global_data.h>
19c31285 24#include <dm/device-internal.h>
3db71108 25#include <u-boot/crc.h>
8c66497e 26
4415f1d1 27#ifndef CONFIG_SPL_BUILD
b500c92b 28#define INITENV
4415f1d1
SG
29#endif
30
25d90ad4
PD
31#define OFFSET_INVALID (~(u32)0)
32
7319bcaf 33#ifdef CONFIG_ENV_OFFSET_REDUND
25d90ad4
PD
34#define ENV_OFFSET_REDUND CONFIG_ENV_OFFSET_REDUND
35
eb58a7fc
IG
36static ulong env_offset = CONFIG_ENV_OFFSET;
37static ulong env_new_offset = CONFIG_ENV_OFFSET_REDUND;
25d90ad4
PD
38
39#else
40
41#define ENV_OFFSET_REDUND OFFSET_INVALID
42
a3110f01 43#endif /* CONFIG_ENV_OFFSET_REDUND */
7319bcaf 44
8c66497e
HS
45DECLARE_GLOBAL_DATA_PTR;
46
ecf15442 47static int setup_flash_device(struct spi_flash **env_flash)
7319bcaf 48{
56c40460 49#if CONFIG_IS_ENABLED(DM_SPI_FLASH)
19c31285 50 struct udevice *new;
afa81a77 51 int ret;
19c31285 52
96907c0f 53 /* speed and mode will be read from DT */
19c31285 54 ret = spi_flash_probe_bus_cs(CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS,
25a17652
KP
55 CONFIG_ENV_SPI_MAX_HZ, CONFIG_ENV_SPI_MODE,
56 &new);
19c31285 57 if (ret) {
0ac7d722 58 env_set_default("spi_flash_probe_bus_cs() failed", 0);
c5951991 59 return ret;
19c31285
GQ
60 }
61
ecf15442 62 *env_flash = dev_get_uclass_priv(new);
19c31285 63#else
ecf15442
PD
64 *env_flash = spi_flash_probe(CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS,
65 CONFIG_ENV_SPI_MAX_HZ, CONFIG_ENV_SPI_MODE);
66 if (!*env_flash) {
c8cbf170
JT
67 env_set_default("spi_flash_probe() failed", 0);
68 return -EIO;
7319bcaf 69 }
19c31285 70#endif
afa81a77
AF
71 return 0;
72}
73
74#if defined(CONFIG_ENV_OFFSET_REDUND)
e5bce247 75static int env_sf_save(void)
afa81a77
AF
76{
77 env_t env_new;
d3716dd6 78 char *saved_buffer = NULL, flag = ENV_REDUND_OBSOLETE;
bcb44f62 79 u32 saved_size = 0, saved_offset = 0, sector;
4da7347d 80 u32 sect_size = CONFIG_ENV_SECT_SIZE;
afa81a77 81 int ret;
ecf15442 82 struct spi_flash *env_flash;
afa81a77 83
ecf15442 84 ret = setup_flash_device(&env_flash);
afa81a77
AF
85 if (ret)
86 return ret;
7319bcaf 87
bcb44f62
RV
88 if (IS_ENABLED(CONFIG_ENV_SECT_SIZE_AUTO))
89 sect_size = env_flash->mtd.erasesize;
90
7ce1526e
MV
91 ret = env_export(&env_new);
92 if (ret)
c5951991 93 return -EIO;
d3716dd6 94 env_new.flags = ENV_REDUND_ACTIVE;
ea882baf 95
203e94f6 96 if (gd->env_valid == ENV_VALID) {
a3110f01
SB
97 env_new_offset = CONFIG_ENV_OFFSET_REDUND;
98 env_offset = CONFIG_ENV_OFFSET;
99 } else {
100 env_new_offset = CONFIG_ENV_OFFSET;
101 env_offset = CONFIG_ENV_OFFSET_REDUND;
102 }
103
7319bcaf 104 /* Is the sector larger than the env (i.e. embedded) */
4da7347d
RV
105 if (sect_size > CONFIG_ENV_SIZE) {
106 saved_size = sect_size - CONFIG_ENV_SIZE;
7319bcaf 107 saved_offset = env_new_offset + CONFIG_ENV_SIZE;
7dd01744 108 saved_buffer = memalign(ARCH_DMA_MINALIGN, saved_size);
7319bcaf 109 if (!saved_buffer) {
c5951991 110 ret = -ENOMEM;
7319bcaf
WW
111 goto done;
112 }
9ba5e5bc
HS
113 ret = spi_flash_read(env_flash, saved_offset,
114 saved_size, saved_buffer);
7319bcaf
WW
115 if (ret)
116 goto done;
117 }
118
4da7347d 119 sector = DIV_ROUND_UP(CONFIG_ENV_SIZE, sect_size);
7319bcaf
WW
120
121 puts("Erasing SPI flash...");
122 ret = spi_flash_erase(env_flash, env_new_offset,
4da7347d 123 sector * sect_size);
7319bcaf
WW
124 if (ret)
125 goto done;
126
127 puts("Writing to SPI flash...");
7319bcaf 128
a3110f01 129 ret = spi_flash_write(env_flash, env_new_offset,
cd0f4fa1 130 CONFIG_ENV_SIZE, &env_new);
7319bcaf
WW
131 if (ret)
132 goto done;
133
4da7347d 134 if (sect_size > CONFIG_ENV_SIZE) {
7319bcaf
WW
135 ret = spi_flash_write(env_flash, saved_offset,
136 saved_size, saved_buffer);
137 if (ret)
138 goto done;
139 }
140
eb58a7fc 141 ret = spi_flash_write(env_flash, env_offset + offsetof(env_t, flags),
cd0f4fa1 142 sizeof(env_new.flags), &flag);
a3110f01
SB
143 if (ret)
144 goto done;
7319bcaf 145
7319bcaf
WW
146 puts("done\n");
147
203e94f6 148 gd->env_valid = gd->env_valid == ENV_REDUND ? ENV_VALID : ENV_REDUND;
a3110f01 149
2dc55d9e 150 printf("Valid environment: %d\n", (int)gd->env_valid);
a3110f01 151
ea5641ec 152done:
c2d00364 153 spi_flash_free(env_flash);
c2d00364 154
7319bcaf
WW
155 if (saved_buffer)
156 free(saved_buffer);
eb58a7fc 157
7319bcaf
WW
158 return ret;
159}
160
c5951991 161static int env_sf_load(void)
7319bcaf
WW
162{
163 int ret;
80719938
SG
164 int read1_fail, read2_fail;
165 env_t *tmp_env1, *tmp_env2;
ecf15442 166 struct spi_flash *env_flash;
7319bcaf 167
7dd01744
RB
168 tmp_env1 = (env_t *)memalign(ARCH_DMA_MINALIGN,
169 CONFIG_ENV_SIZE);
170 tmp_env2 = (env_t *)memalign(ARCH_DMA_MINALIGN,
171 CONFIG_ENV_SIZE);
ea882baf 172 if (!tmp_env1 || !tmp_env2) {
0ac7d722 173 env_set_default("malloc() failed", 0);
c5951991 174 ret = -EIO;
2dc55d9e 175 goto out;
7319bcaf
WW
176 }
177
ecf15442 178 ret = setup_flash_device(&env_flash);
8fee8845 179 if (ret)
2dc55d9e 180 goto out;
7319bcaf 181
9ba5e5bc
HS
182 read1_fail = spi_flash_read(env_flash, CONFIG_ENV_OFFSET,
183 CONFIG_ENV_SIZE, tmp_env1);
184 read2_fail = spi_flash_read(env_flash, CONFIG_ENV_OFFSET_REDUND,
185 CONFIG_ENV_SIZE, tmp_env2);
ea882baf 186
80719938 187 ret = env_import_redund((char *)tmp_env1, read1_fail, (char *)tmp_env2,
890feeca 188 read2_fail, H_EXTERNAL);
7319bcaf 189
7319bcaf 190 spi_flash_free(env_flash);
7319bcaf 191out:
ea882baf
WD
192 free(tmp_env1);
193 free(tmp_env2);
c5951991
SG
194
195 return ret;
7319bcaf
WW
196}
197#else
e5bce247 198static int env_sf_save(void)
8c66497e 199{
bcb44f62 200 u32 saved_size = 0, saved_offset = 0, sector;
4da7347d 201 u32 sect_size = CONFIG_ENV_SECT_SIZE;
7ce1526e 202 char *saved_buffer = NULL;
eb58a7fc 203 int ret = 1;
cd0f4fa1 204 env_t env_new;
ecf15442 205 struct spi_flash *env_flash;
19c31285 206
ecf15442 207 ret = setup_flash_device(&env_flash);
afa81a77
AF
208 if (ret)
209 return ret;
8c66497e 210
bcb44f62
RV
211 if (IS_ENABLED(CONFIG_ENV_SECT_SIZE_AUTO))
212 sect_size = env_flash->mtd.erasesize;
213
5b3375ac 214 /* Is the sector larger than the env (i.e. embedded) */
4da7347d
RV
215 if (sect_size > CONFIG_ENV_SIZE) {
216 saved_size = sect_size - CONFIG_ENV_SIZE;
5b3375ac
MF
217 saved_offset = CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE;
218 saved_buffer = malloc(saved_size);
eb58a7fc 219 if (!saved_buffer)
5b3375ac 220 goto done;
eb58a7fc 221
9ba5e5bc
HS
222 ret = spi_flash_read(env_flash, saved_offset,
223 saved_size, saved_buffer);
5b3375ac
MF
224 if (ret)
225 goto done;
226 }
227
7ce1526e
MV
228 ret = env_export(&env_new);
229 if (ret)
a3110f01 230 goto done;
a3110f01 231
4da7347d 232 sector = DIV_ROUND_UP(CONFIG_ENV_SIZE, sect_size);
0b2e5bbe 233
8c66497e 234 puts("Erasing SPI flash...");
a3110f01 235 ret = spi_flash_erase(env_flash, CONFIG_ENV_OFFSET,
4da7347d 236 sector * sect_size);
5b3375ac
MF
237 if (ret)
238 goto done;
8c66497e
HS
239
240 puts("Writing to SPI flash...");
a3110f01 241 ret = spi_flash_write(env_flash, CONFIG_ENV_OFFSET,
cd0f4fa1 242 CONFIG_ENV_SIZE, &env_new);
5b3375ac
MF
243 if (ret)
244 goto done;
8c66497e 245
4da7347d 246 if (sect_size > CONFIG_ENV_SIZE) {
a3110f01
SB
247 ret = spi_flash_write(env_flash, saved_offset,
248 saved_size, saved_buffer);
5b3375ac
MF
249 if (ret)
250 goto done;
251 }
252
253 ret = 0;
8c66497e 254 puts("done\n");
5b3375ac 255
ea5641ec 256done:
c2d00364 257 spi_flash_free(env_flash);
c2d00364 258
5b3375ac
MF
259 if (saved_buffer)
260 free(saved_buffer);
eb58a7fc 261
5b3375ac 262 return ret;
8c66497e
HS
263}
264
c5951991 265static int env_sf_load(void)
8c66497e
HS
266{
267 int ret;
5a89fa92 268 char *buf = NULL;
ecf15442 269 struct spi_flash *env_flash;
8c66497e 270
7dd01744 271 buf = (char *)memalign(ARCH_DMA_MINALIGN, CONFIG_ENV_SIZE);
c041c60c 272 if (!buf) {
0ac7d722 273 env_set_default("malloc() failed", 0);
c5951991 274 return -EIO;
ea882baf 275 }
8c66497e 276
ecf15442 277 ret = setup_flash_device(&env_flash);
c041c60c
AF
278 if (ret)
279 goto out;
280
9ba5e5bc
HS
281 ret = spi_flash_read(env_flash,
282 CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE, buf);
ea882baf 283 if (ret) {
0ac7d722 284 env_set_default("spi_flash_read() failed", 0);
c041c60c 285 goto err_read;
ea882baf 286 }
8c66497e 287
890feeca 288 ret = env_import(buf, 1, H_EXTERNAL);
42a1820b 289 if (!ret)
203e94f6 290 gd->env_valid = ENV_VALID;
c041c60c
AF
291
292err_read:
8c66497e 293 spi_flash_free(env_flash);
c041c60c
AF
294out:
295 free(buf);
c5951991
SG
296
297 return ret;
8c66497e 298}
7319bcaf 299#endif
8c66497e 300
25d90ad4
PD
301static int env_sf_erase(void)
302{
303 int ret;
304 env_t env;
ecf15442 305 struct spi_flash *env_flash;
25d90ad4 306
ecf15442 307 ret = setup_flash_device(&env_flash);
25d90ad4
PD
308 if (ret)
309 return ret;
310
311 memset(&env, 0, sizeof(env_t));
312 ret = spi_flash_write(env_flash, CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE, &env);
313 if (ret)
314 goto done;
315
316 if (ENV_OFFSET_REDUND != OFFSET_INVALID)
317 ret = spi_flash_write(env_flash, ENV_OFFSET_REDUND, CONFIG_ENV_SIZE, &env);
318
319done:
320 spi_flash_free(env_flash);
25d90ad4
PD
321
322 return ret;
323}
324
a09fea1d 325#if CONFIG_ENV_ADDR != 0x0
119c01c2
RB
326__weak void *env_sf_get_env_addr(void)
327{
328 return (void *)CONFIG_ENV_ADDR;
329}
330#endif
331
a09fea1d 332#if defined(INITENV) && (CONFIG_ENV_ADDR != 0x0)
92765f45
HS
333/*
334 * check if Environment on CONFIG_ENV_ADDR is valid.
335 */
336static int env_sf_init_addr(void)
b500c92b 337{
119c01c2 338 env_t *env_ptr = (env_t *)env_sf_get_env_addr();
b500c92b
AK
339
340 if (crc32(0, env_ptr->data, ENV_SIZE) == env_ptr->crc) {
341 gd->env_addr = (ulong)&(env_ptr->data);
342 gd->env_valid = 1;
343 } else {
344 gd->env_addr = (ulong)&default_environment[0];
345 gd->env_valid = 1;
346 }
347
348 return 0;
349}
350#endif
351
92765f45
HS
352#if defined(CONFIG_ENV_SPI_EARLY)
353/*
354 * early load environment from SPI flash (before relocation)
355 * and check if it is valid.
356 */
357static int env_sf_init_early(void)
358{
359 int ret;
360 int read1_fail;
361 int read2_fail;
362 int crc1_ok;
363 env_t *tmp_env2 = NULL;
364 env_t *tmp_env1;
ecf15442 365 struct spi_flash *env_flash;
92765f45
HS
366
367 /*
368 * if malloc is not ready yet, we cannot use
369 * this part yet.
370 */
371 if (!gd->malloc_limit)
372 return -ENOENT;
373
374 tmp_env1 = (env_t *)memalign(ARCH_DMA_MINALIGN,
375 CONFIG_ENV_SIZE);
376 if (IS_ENABLED(CONFIG_SYS_REDUNDAND_ENVIRONMENT))
377 tmp_env2 = (env_t *)memalign(ARCH_DMA_MINALIGN,
378 CONFIG_ENV_SIZE);
379
380 if (!tmp_env1 || !tmp_env2)
381 goto out;
382
ecf15442 383 ret = setup_flash_device(&env_flash);
92765f45
HS
384 if (ret)
385 goto out;
386
387 read1_fail = spi_flash_read(env_flash, CONFIG_ENV_OFFSET,
388 CONFIG_ENV_SIZE, tmp_env1);
389
390 if (IS_ENABLED(CONFIG_SYS_REDUNDAND_ENVIRONMENT)) {
391 read2_fail = spi_flash_read(env_flash,
392 CONFIG_ENV_OFFSET_REDUND,
393 CONFIG_ENV_SIZE, tmp_env2);
394 ret = env_check_redund((char *)tmp_env1, read1_fail,
395 (char *)tmp_env2, read2_fail);
396
b9c3052f 397 if (ret < 0)
92765f45
HS
398 goto err_read;
399
400 if (gd->env_valid == ENV_VALID)
401 gd->env_addr = (unsigned long)&tmp_env1->data;
402 else
403 gd->env_addr = (unsigned long)&tmp_env2->data;
404 } else {
405 if (read1_fail)
406 goto err_read;
407
408 crc1_ok = crc32(0, tmp_env1->data, ENV_SIZE) ==
409 tmp_env1->crc;
410 if (!crc1_ok)
411 goto err_read;
412
413 /* if valid -> this is our env */
414 gd->env_valid = ENV_VALID;
415 gd->env_addr = (unsigned long)&tmp_env1->data;
416 }
417
c2d00364 418 spi_flash_free(env_flash);
c2d00364 419
92765f45
HS
420 return 0;
421err_read:
422 spi_flash_free(env_flash);
ecf15442 423
92765f45
HS
424 free(tmp_env1);
425 if (IS_ENABLED(CONFIG_SYS_REDUNDAND_ENVIRONMENT))
426 free(tmp_env2);
427out:
428 /* env is not valid. always return 0 */
429 gd->env_valid = ENV_INVALID;
430 return 0;
431}
432#endif
433
434static int env_sf_init(void)
435{
436#if defined(INITENV) && (CONFIG_ENV_ADDR != 0x0)
437 return env_sf_init_addr();
438#elif defined(CONFIG_ENV_SPI_EARLY)
439 return env_sf_init_early();
440#endif
441 /*
46ce9e77
HS
442 * return here -ENOENT, so env_init()
443 * can set the init bit and later if no
444 * other Environment storage is defined
445 * can set the default environment
92765f45 446 */
46ce9e77 447 return -ENOENT;
92765f45
HS
448}
449
4415f1d1
SG
450U_BOOT_ENV_LOCATION(sf) = {
451 .location = ENVL_SPI_FLASH,
22140d16 452 ENV_NAME("SPIFlash")
e5bce247 453 .load = env_sf_load,
e41f55b3 454 .save = ENV_SAVE_PTR(env_sf_save),
25d90ad4 455 .erase = ENV_ERASE_PTR(env_sf_erase),
b500c92b 456 .init = env_sf_init,
4415f1d1 457};
This page took 0.569666 seconds and 4 git commands to generate.