~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to roms/u-boot/common/env_sf.c

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * (C) Copyright 2000-2010
 
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>
 
7
 *
 
8
 * (C) Copyright 2008 Atmel Corporation
 
9
 *
 
10
 * SPDX-License-Identifier:     GPL-2.0+
 
11
 */
 
12
#include <common.h>
 
13
#include <environment.h>
 
14
#include <malloc.h>
 
15
#include <spi_flash.h>
 
16
#include <search.h>
 
17
#include <errno.h>
 
18
 
 
19
#ifndef CONFIG_ENV_SPI_BUS
 
20
# define CONFIG_ENV_SPI_BUS     0
 
21
#endif
 
22
#ifndef CONFIG_ENV_SPI_CS
 
23
# define CONFIG_ENV_SPI_CS      0
 
24
#endif
 
25
#ifndef CONFIG_ENV_SPI_MAX_HZ
 
26
# define CONFIG_ENV_SPI_MAX_HZ  1000000
 
27
#endif
 
28
#ifndef CONFIG_ENV_SPI_MODE
 
29
# define CONFIG_ENV_SPI_MODE    SPI_MODE_3
 
30
#endif
 
31
 
 
32
#ifdef CONFIG_ENV_OFFSET_REDUND
 
33
static ulong env_offset         = CONFIG_ENV_OFFSET;
 
34
static ulong env_new_offset     = CONFIG_ENV_OFFSET_REDUND;
 
35
 
 
36
#define ACTIVE_FLAG     1
 
37
#define OBSOLETE_FLAG   0
 
38
#endif /* CONFIG_ENV_OFFSET_REDUND */
 
39
 
 
40
DECLARE_GLOBAL_DATA_PTR;
 
41
 
 
42
char *env_name_spec = "SPI Flash";
 
43
 
 
44
static struct spi_flash *env_flash;
 
45
 
 
46
#if defined(CONFIG_ENV_OFFSET_REDUND)
 
47
int saveenv(void)
 
48
{
 
49
        env_t   env_new;
 
50
        char    *saved_buffer = NULL, flag = OBSOLETE_FLAG;
 
51
        u32     saved_size, saved_offset, sector = 1;
 
52
        int     ret;
 
53
 
 
54
        if (!env_flash) {
 
55
                env_flash = spi_flash_probe(CONFIG_ENV_SPI_BUS,
 
56
                        CONFIG_ENV_SPI_CS,
 
57
                        CONFIG_ENV_SPI_MAX_HZ, CONFIG_ENV_SPI_MODE);
 
58
                if (!env_flash) {
 
59
                        set_default_env("!spi_flash_probe() failed");
 
60
                        return 1;
 
61
                }
 
62
        }
 
63
 
 
64
        ret = env_export(&env_new);
 
65
        if (ret)
 
66
                return ret;
 
67
        env_new.flags   = ACTIVE_FLAG;
 
68
 
 
69
        if (gd->env_valid == 1) {
 
70
                env_new_offset = CONFIG_ENV_OFFSET_REDUND;
 
71
                env_offset = CONFIG_ENV_OFFSET;
 
72
        } else {
 
73
                env_new_offset = CONFIG_ENV_OFFSET;
 
74
                env_offset = CONFIG_ENV_OFFSET_REDUND;
 
75
        }
 
76
 
 
77
        /* Is the sector larger than the env (i.e. embedded) */
 
78
        if (CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE) {
 
79
                saved_size = CONFIG_ENV_SECT_SIZE - CONFIG_ENV_SIZE;
 
80
                saved_offset = env_new_offset + CONFIG_ENV_SIZE;
 
81
                saved_buffer = malloc(saved_size);
 
82
                if (!saved_buffer) {
 
83
                        ret = 1;
 
84
                        goto done;
 
85
                }
 
86
                ret = spi_flash_read(env_flash, saved_offset,
 
87
                                        saved_size, saved_buffer);
 
88
                if (ret)
 
89
                        goto done;
 
90
        }
 
91
 
 
92
        if (CONFIG_ENV_SIZE > CONFIG_ENV_SECT_SIZE) {
 
93
                sector = CONFIG_ENV_SIZE / CONFIG_ENV_SECT_SIZE;
 
94
                if (CONFIG_ENV_SIZE % CONFIG_ENV_SECT_SIZE)
 
95
                        sector++;
 
96
        }
 
97
 
 
98
        puts("Erasing SPI flash...");
 
99
        ret = spi_flash_erase(env_flash, env_new_offset,
 
100
                                sector * CONFIG_ENV_SECT_SIZE);
 
101
        if (ret)
 
102
                goto done;
 
103
 
 
104
        puts("Writing to SPI flash...");
 
105
 
 
106
        ret = spi_flash_write(env_flash, env_new_offset,
 
107
                CONFIG_ENV_SIZE, &env_new);
 
108
        if (ret)
 
109
                goto done;
 
110
 
 
111
        if (CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE) {
 
112
                ret = spi_flash_write(env_flash, saved_offset,
 
113
                                        saved_size, saved_buffer);
 
114
                if (ret)
 
115
                        goto done;
 
116
        }
 
117
 
 
118
        ret = spi_flash_write(env_flash, env_offset + offsetof(env_t, flags),
 
119
                                sizeof(env_new.flags), &flag);
 
120
        if (ret)
 
121
                goto done;
 
122
 
 
123
        puts("done\n");
 
124
 
 
125
        gd->env_valid = gd->env_valid == 2 ? 1 : 2;
 
126
 
 
127
        printf("Valid environment: %d\n", (int)gd->env_valid);
 
128
 
 
129
 done:
 
130
        if (saved_buffer)
 
131
                free(saved_buffer);
 
132
 
 
133
        return ret;
 
134
}
 
135
 
 
136
void env_relocate_spec(void)
 
137
{
 
138
        int ret;
 
139
        int crc1_ok = 0, crc2_ok = 0;
 
140
        env_t *tmp_env1 = NULL;
 
141
        env_t *tmp_env2 = NULL;
 
142
        env_t *ep = NULL;
 
143
 
 
144
        tmp_env1 = (env_t *)malloc(CONFIG_ENV_SIZE);
 
145
        tmp_env2 = (env_t *)malloc(CONFIG_ENV_SIZE);
 
146
 
 
147
        if (!tmp_env1 || !tmp_env2) {
 
148
                set_default_env("!malloc() failed");
 
149
                goto out;
 
150
        }
 
151
 
 
152
        env_flash = spi_flash_probe(CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS,
 
153
                        CONFIG_ENV_SPI_MAX_HZ, CONFIG_ENV_SPI_MODE);
 
154
        if (!env_flash) {
 
155
                set_default_env("!spi_flash_probe() failed");
 
156
                goto out;
 
157
        }
 
158
 
 
159
        ret = spi_flash_read(env_flash, CONFIG_ENV_OFFSET,
 
160
                                CONFIG_ENV_SIZE, tmp_env1);
 
161
        if (ret) {
 
162
                set_default_env("!spi_flash_read() failed");
 
163
                goto err_read;
 
164
        }
 
165
 
 
166
        if (crc32(0, tmp_env1->data, ENV_SIZE) == tmp_env1->crc)
 
167
                crc1_ok = 1;
 
168
 
 
169
        ret = spi_flash_read(env_flash, CONFIG_ENV_OFFSET_REDUND,
 
170
                                CONFIG_ENV_SIZE, tmp_env2);
 
171
        if (!ret) {
 
172
                if (crc32(0, tmp_env2->data, ENV_SIZE) == tmp_env2->crc)
 
173
                        crc2_ok = 1;
 
174
        }
 
175
 
 
176
        if (!crc1_ok && !crc2_ok) {
 
177
                set_default_env("!bad CRC");
 
178
                goto err_read;
 
179
        } else if (crc1_ok && !crc2_ok) {
 
180
                gd->env_valid = 1;
 
181
        } else if (!crc1_ok && crc2_ok) {
 
182
                gd->env_valid = 2;
 
183
        } else if (tmp_env1->flags == ACTIVE_FLAG &&
 
184
                   tmp_env2->flags == OBSOLETE_FLAG) {
 
185
                gd->env_valid = 1;
 
186
        } else if (tmp_env1->flags == OBSOLETE_FLAG &&
 
187
                   tmp_env2->flags == ACTIVE_FLAG) {
 
188
                gd->env_valid = 2;
 
189
        } else if (tmp_env1->flags == tmp_env2->flags) {
 
190
                gd->env_valid = 2;
 
191
        } else if (tmp_env1->flags == 0xFF) {
 
192
                gd->env_valid = 2;
 
193
        } else {
 
194
                /*
 
195
                 * this differs from code in env_flash.c, but I think a sane
 
196
                 * default path is desirable.
 
197
                 */
 
198
                gd->env_valid = 2;
 
199
        }
 
200
 
 
201
        if (gd->env_valid == 1)
 
202
                ep = tmp_env1;
 
203
        else
 
204
                ep = tmp_env2;
 
205
 
 
206
        ret = env_import((char *)ep, 0);
 
207
        if (!ret) {
 
208
                error("Cannot import environment: errno = %d\n", errno);
 
209
                set_default_env("env_import failed");
 
210
        }
 
211
 
 
212
err_read:
 
213
        spi_flash_free(env_flash);
 
214
        env_flash = NULL;
 
215
out:
 
216
        free(tmp_env1);
 
217
        free(tmp_env2);
 
218
}
 
219
#else
 
220
int saveenv(void)
 
221
{
 
222
        u32     saved_size, saved_offset, sector = 1;
 
223
        char    *saved_buffer = NULL;
 
224
        int     ret = 1;
 
225
        env_t   env_new;
 
226
 
 
227
        if (!env_flash) {
 
228
                env_flash = spi_flash_probe(CONFIG_ENV_SPI_BUS,
 
229
                        CONFIG_ENV_SPI_CS,
 
230
                        CONFIG_ENV_SPI_MAX_HZ, CONFIG_ENV_SPI_MODE);
 
231
                if (!env_flash) {
 
232
                        set_default_env("!spi_flash_probe() failed");
 
233
                        return 1;
 
234
                }
 
235
        }
 
236
 
 
237
        /* Is the sector larger than the env (i.e. embedded) */
 
238
        if (CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE) {
 
239
                saved_size = CONFIG_ENV_SECT_SIZE - CONFIG_ENV_SIZE;
 
240
                saved_offset = CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE;
 
241
                saved_buffer = malloc(saved_size);
 
242
                if (!saved_buffer)
 
243
                        goto done;
 
244
 
 
245
                ret = spi_flash_read(env_flash, saved_offset,
 
246
                        saved_size, saved_buffer);
 
247
                if (ret)
 
248
                        goto done;
 
249
        }
 
250
 
 
251
        if (CONFIG_ENV_SIZE > CONFIG_ENV_SECT_SIZE) {
 
252
                sector = CONFIG_ENV_SIZE / CONFIG_ENV_SECT_SIZE;
 
253
                if (CONFIG_ENV_SIZE % CONFIG_ENV_SECT_SIZE)
 
254
                        sector++;
 
255
        }
 
256
 
 
257
        ret = env_export(&env_new);
 
258
        if (ret)
 
259
                goto done;
 
260
 
 
261
        puts("Erasing SPI flash...");
 
262
        ret = spi_flash_erase(env_flash, CONFIG_ENV_OFFSET,
 
263
                sector * CONFIG_ENV_SECT_SIZE);
 
264
        if (ret)
 
265
                goto done;
 
266
 
 
267
        puts("Writing to SPI flash...");
 
268
        ret = spi_flash_write(env_flash, CONFIG_ENV_OFFSET,
 
269
                CONFIG_ENV_SIZE, &env_new);
 
270
        if (ret)
 
271
                goto done;
 
272
 
 
273
        if (CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE) {
 
274
                ret = spi_flash_write(env_flash, saved_offset,
 
275
                        saved_size, saved_buffer);
 
276
                if (ret)
 
277
                        goto done;
 
278
        }
 
279
 
 
280
        ret = 0;
 
281
        puts("done\n");
 
282
 
 
283
 done:
 
284
        if (saved_buffer)
 
285
                free(saved_buffer);
 
286
 
 
287
        return ret;
 
288
}
 
289
 
 
290
void env_relocate_spec(void)
 
291
{
 
292
        int ret;
 
293
        char *buf = NULL;
 
294
 
 
295
        buf = (char *)malloc(CONFIG_ENV_SIZE);
 
296
        env_flash = spi_flash_probe(CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS,
 
297
                        CONFIG_ENV_SPI_MAX_HZ, CONFIG_ENV_SPI_MODE);
 
298
        if (!env_flash) {
 
299
                set_default_env("!spi_flash_probe() failed");
 
300
                if (buf)
 
301
                        free(buf);
 
302
                return;
 
303
        }
 
304
 
 
305
        ret = spi_flash_read(env_flash,
 
306
                CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE, buf);
 
307
        if (ret) {
 
308
                set_default_env("!spi_flash_read() failed");
 
309
                goto out;
 
310
        }
 
311
 
 
312
        ret = env_import(buf, 1);
 
313
        if (ret)
 
314
                gd->env_valid = 1;
 
315
out:
 
316
        spi_flash_free(env_flash);
 
317
        if (buf)
 
318
                free(buf);
 
319
        env_flash = NULL;
 
320
}
 
321
#endif
 
322
 
 
323
int env_init(void)
 
324
{
 
325
        /* SPI flash isn't usable before relocation */
 
326
        gd->env_addr = (ulong)&default_environment[0];
 
327
        gd->env_valid = 1;
 
328
 
 
329
        return 0;
 
330
}