Blame view
common/env_mmc.c
6.18 KB
a80603598 Save environment ... |
1 |
/* |
97039ab98 env_mmc: Allow bo... |
2 |
* (C) Copyright 2008-2011 Freescale Semiconductor, Inc. |
a80603598 Save environment ... |
3 |
* |
3765b3e7b Coding Style clea... |
4 |
* SPDX-License-Identifier: GPL-2.0+ |
a80603598 Save environment ... |
5 6 7 8 9 10 11 12 13 14 15 |
*/ /* #define DEBUG */ #include <common.h> #include <command.h> #include <environment.h> #include <linux/stddef.h> #include <malloc.h> #include <mmc.h> |
6d1d51b32 env_mmc: fix comp... |
16 |
#include <search.h> |
e79f48393 env_mmc: fix cann... |
17 |
#include <errno.h> |
a80603598 Save environment ... |
18 |
|
d196bd880 env_mmc: add supp... |
19 20 21 22 |
#if defined(CONFIG_ENV_SIZE_REDUND) && \ (CONFIG_ENV_SIZE_REDUND != CONFIG_ENV_SIZE) #error CONFIG_ENV_SIZE_REDUND should be the same as CONFIG_ENV_SIZE #endif |
a80603598 Save environment ... |
23 24 25 |
char *env_name_spec = "MMC"; #ifdef ENV_IS_EMBEDDED |
994bc671c env: move extern ... |
26 |
env_t *env_ptr = &environment; |
a80603598 Save environment ... |
27 |
#else /* ! ENV_IS_EMBEDDED */ |
e8db8f71c env: clean env_mm... |
28 |
env_t *env_ptr; |
a80603598 Save environment ... |
29 |
#endif /* ENV_IS_EMBEDDED */ |
a80603598 Save environment ... |
30 |
DECLARE_GLOBAL_DATA_PTR; |
97039ab98 env_mmc: Allow bo... |
31 32 33 |
#if !defined(CONFIG_ENV_OFFSET) #define CONFIG_ENV_OFFSET 0 #endif |
d196bd880 env_mmc: add supp... |
34 |
__weak int mmc_get_env_addr(struct mmc *mmc, int copy, u32 *env_addr) |
97039ab98 env_mmc: Allow bo... |
35 |
{ |
5c088ee84 env_mmc: allow ne... |
36 37 38 |
s64 offset; offset = CONFIG_ENV_OFFSET; |
d196bd880 env_mmc: add supp... |
39 40 |
#ifdef CONFIG_ENV_OFFSET_REDUND if (copy) |
5c088ee84 env_mmc: allow ne... |
41 |
offset = CONFIG_ENV_OFFSET_REDUND; |
d196bd880 env_mmc: add supp... |
42 |
#endif |
5c088ee84 env_mmc: allow ne... |
43 44 45 46 47 |
if (offset < 0) offset += mmc->capacity; *env_addr = offset; |
97039ab98 env_mmc: Allow bo... |
48 49 |
return 0; } |
97039ab98 env_mmc: Allow bo... |
50 |
|
a80603598 Save environment ... |
51 52 53 |
int env_init(void) { /* use default */ |
e8db8f71c env: clean env_mm... |
54 55 |
gd->env_addr = (ulong)&default_environment[0]; gd->env_valid = 1; |
a80603598 Save environment ... |
56 57 58 |
return 0; } |
e8db8f71c env: clean env_mm... |
59 |
static int init_mmc_for_env(struct mmc *mmc) |
a80603598 Save environment ... |
60 61 62 63 64 65 66 67 68 69 |
{ if (!mmc) { puts("No MMC card found "); return -1; } if (mmc_init(mmc)) { puts("MMC init failed "); |
e8db8f71c env: clean env_mm... |
70 |
return -1; |
a80603598 Save environment ... |
71 |
} |
9404a5fc7 env_mmc: allow en... |
72 73 74 75 76 77 78 79 80 81 |
#ifdef CONFIG_SYS_MMC_ENV_PART if (CONFIG_SYS_MMC_ENV_PART != mmc->part_num) { if (mmc_switch_part(CONFIG_SYS_MMC_ENV_DEV, CONFIG_SYS_MMC_ENV_PART)) { puts("MMC partition switch failed "); return -1; } } #endif |
a80603598 Save environment ... |
82 83 |
return 0; } |
9404a5fc7 env_mmc: allow en... |
84 85 86 87 88 89 90 91 |
static void fini_mmc_for_env(struct mmc *mmc) { #ifdef CONFIG_SYS_MMC_ENV_PART if (CONFIG_SYS_MMC_ENV_PART != mmc->part_num) mmc_switch_part(CONFIG_SYS_MMC_ENV_DEV, mmc->part_num); #endif } |
a80603598 Save environment ... |
92 |
#ifdef CONFIG_CMD_SAVEENV |
e8db8f71c env: clean env_mm... |
93 94 |
static inline int write_env(struct mmc *mmc, unsigned long size, unsigned long offset, const void *buffer) |
a80603598 Save environment ... |
95 96 |
{ uint blk_start, blk_cnt, n; |
e8db8f71c env: clean env_mm... |
97 98 |
blk_start = ALIGN(offset, mmc->write_bl_len) / mmc->write_bl_len; blk_cnt = ALIGN(size, mmc->write_bl_len) / mmc->write_bl_len; |
a80603598 Save environment ... |
99 100 101 102 103 104 |
n = mmc->block_dev.block_write(CONFIG_SYS_MMC_ENV_DEV, blk_start, blk_cnt, (u_char *)buffer); return (n == blk_cnt) ? 0 : -1; } |
d196bd880 env_mmc: add supp... |
105 106 107 |
#ifdef CONFIG_ENV_OFFSET_REDUND static unsigned char env_flags; #endif |
a80603598 Save environment ... |
108 109 |
int saveenv(void) { |
cd0f4fa1c Revert "env: fix ... |
110 |
ALLOC_CACHE_ALIGN_BUFFER(env_t, env_new, 1); |
e79f48393 env_mmc: fix cann... |
111 112 |
ssize_t len; char *res; |
a80603598 Save environment ... |
113 |
struct mmc *mmc = find_mmc_device(CONFIG_SYS_MMC_ENV_DEV); |
e8db8f71c env: clean env_mm... |
114 |
u32 offset; |
d196bd880 env_mmc: add supp... |
115 |
int ret, copy = 0; |
a80603598 Save environment ... |
116 |
|
9404a5fc7 env_mmc: allow en... |
117 |
if (init_mmc_for_env(mmc)) |
97039ab98 env_mmc: Allow bo... |
118 |
return 1; |
cd0f4fa1c Revert "env: fix ... |
119 |
res = (char *)&env_new->data; |
be11235ab env: Hide '.' var... |
120 |
len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL); |
e79f48393 env_mmc: fix cann... |
121 122 123 |
if (len < 0) { error("Cannot export environment: errno = %d ", errno); |
9404a5fc7 env_mmc: allow en... |
124 125 |
ret = 1; goto fini; |
e79f48393 env_mmc: fix cann... |
126 |
} |
e8db8f71c env: clean env_mm... |
127 |
|
cd0f4fa1c Revert "env: fix ... |
128 |
env_new->crc = crc32(0, &env_new->data[0], ENV_SIZE); |
d196bd880 env_mmc: add supp... |
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
#ifdef CONFIG_ENV_OFFSET_REDUND env_new->flags = ++env_flags; /* increase the serial */ if (gd->env_valid == 1) copy = 1; #endif if (mmc_get_env_addr(mmc, copy, &offset)) { ret = 1; goto fini; } printf("Writing to %sMMC(%d)... ", copy ? "redundant " : "", CONFIG_SYS_MMC_ENV_DEV); |
4036b6301 env_mmc: align bu... |
144 |
if (write_env(mmc, CONFIG_ENV_SIZE, offset, (u_char *)env_new)) { |
a80603598 Save environment ... |
145 146 |
puts("failed "); |
9404a5fc7 env_mmc: allow en... |
147 148 |
ret = 1; goto fini; |
a80603598 Save environment ... |
149 150 151 152 |
} puts("done "); |
9404a5fc7 env_mmc: allow en... |
153 |
ret = 0; |
d196bd880 env_mmc: add supp... |
154 155 156 |
#ifdef CONFIG_ENV_OFFSET_REDUND gd->env_valid = gd->env_valid == 2 ? 1 : 2; #endif |
9404a5fc7 env_mmc: allow en... |
157 158 159 |
fini: fini_mmc_for_env(mmc); return ret; |
a80603598 Save environment ... |
160 161 |
} #endif /* CONFIG_CMD_SAVEENV */ |
e8db8f71c env: clean env_mm... |
162 163 |
static inline int read_env(struct mmc *mmc, unsigned long size, unsigned long offset, const void *buffer) |
a80603598 Save environment ... |
164 165 |
{ uint blk_start, blk_cnt, n; |
e8db8f71c env: clean env_mm... |
166 167 |
blk_start = ALIGN(offset, mmc->read_bl_len) / mmc->read_bl_len; blk_cnt = ALIGN(size, mmc->read_bl_len) / mmc->read_bl_len; |
a80603598 Save environment ... |
168 169 170 171 172 173 |
n = mmc->block_dev.block_read(CONFIG_SYS_MMC_ENV_DEV, blk_start, blk_cnt, (uchar *)buffer); return (n == blk_cnt) ? 0 : -1; } |
d196bd880 env_mmc: add supp... |
174 175 176 177 178 179 180 181 |
#ifdef CONFIG_ENV_OFFSET_REDUND void env_relocate_spec(void) { #if !defined(ENV_IS_EMBEDDED) struct mmc *mmc = find_mmc_device(CONFIG_SYS_MMC_ENV_DEV); u32 offset1, offset2; int read1_fail = 0, read2_fail = 0; int crc1_ok = 0, crc2_ok = 0; |
452a2722e env_mmc: fix buff... |
182 |
env_t *ep; |
d196bd880 env_mmc: add supp... |
183 |
int ret; |
452a2722e env_mmc: fix buff... |
184 185 |
ALLOC_CACHE_ALIGN_BUFFER(env_t, tmp_env1, 1); ALLOC_CACHE_ALIGN_BUFFER(env_t, tmp_env2, 1); |
d196bd880 env_mmc: add supp... |
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 |
if (tmp_env1 == NULL || tmp_env2 == NULL) { puts("Can't allocate buffers for environment "); ret = 1; goto err; } if (init_mmc_for_env(mmc)) { ret = 1; goto err; } if (mmc_get_env_addr(mmc, 0, &offset1) || mmc_get_env_addr(mmc, 1, &offset2)) { ret = 1; goto fini; } read1_fail = read_env(mmc, CONFIG_ENV_SIZE, offset1, tmp_env1); read2_fail = read_env(mmc, CONFIG_ENV_SIZE, offset2, tmp_env2); if (read1_fail && read2_fail) puts("*** Error - No Valid Environment Area found "); else if (read1_fail || read2_fail) puts("*** Warning - some problems detected " "reading environment; recovered successfully "); crc1_ok = !read1_fail && (crc32(0, tmp_env1->data, ENV_SIZE) == tmp_env1->crc); crc2_ok = !read2_fail && (crc32(0, tmp_env2->data, ENV_SIZE) == tmp_env2->crc); if (!crc1_ok && !crc2_ok) { ret = 1; goto fini; } else if (crc1_ok && !crc2_ok) { gd->env_valid = 1; } else if (!crc1_ok && crc2_ok) { gd->env_valid = 2; } else { /* both ok - check serial */ if (tmp_env1->flags == 255 && tmp_env2->flags == 0) gd->env_valid = 2; else if (tmp_env2->flags == 255 && tmp_env1->flags == 0) gd->env_valid = 1; else if (tmp_env1->flags > tmp_env2->flags) gd->env_valid = 1; else if (tmp_env2->flags > tmp_env1->flags) gd->env_valid = 2; else /* flags are equal - almost impossible */ gd->env_valid = 1; } free(env_ptr); if (gd->env_valid == 1) ep = tmp_env1; else ep = tmp_env2; env_flags = ep->flags; env_import((char *)ep, 0); ret = 0; fini: fini_mmc_for_env(mmc); err: if (ret) set_default_env(NULL); |
d196bd880 env_mmc: add supp... |
257 258 259 |
#endif } #else /* ! CONFIG_ENV_OFFSET_REDUND */ |
a80603598 Save environment ... |
260 261 262 |
void env_relocate_spec(void) { #if !defined(ENV_IS_EMBEDDED) |
cd0f4fa1c Revert "env: fix ... |
263 |
ALLOC_CACHE_ALIGN_BUFFER(char, buf, CONFIG_ENV_SIZE); |
a80603598 Save environment ... |
264 |
struct mmc *mmc = find_mmc_device(CONFIG_SYS_MMC_ENV_DEV); |
97039ab98 env_mmc: Allow bo... |
265 |
u32 offset; |
9404a5fc7 env_mmc: allow en... |
266 |
int ret; |
a80603598 Save environment ... |
267 |
|
9404a5fc7 env_mmc: allow en... |
268 269 270 271 |
if (init_mmc_for_env(mmc)) { ret = 1; goto err; } |
a80603598 Save environment ... |
272 |
|
d196bd880 env_mmc: add supp... |
273 |
if (mmc_get_env_addr(mmc, 0, &offset)) { |
9404a5fc7 env_mmc: allow en... |
274 275 276 |
ret = 1; goto fini; } |
cd0f4fa1c Revert "env: fix ... |
277 |
if (read_env(mmc, CONFIG_ENV_SIZE, offset, buf)) { |
9404a5fc7 env_mmc: allow en... |
278 279 280 |
ret = 1; goto fini; } |
a80603598 Save environment ... |
281 |
|
cd0f4fa1c Revert "env: fix ... |
282 |
env_import(buf, 1); |
9404a5fc7 env_mmc: allow en... |
283 284 285 286 287 288 289 |
ret = 0; fini: fini_mmc_for_env(mmc); err: if (ret) set_default_env(NULL); |
a80603598 Save environment ... |
290 291 |
#endif } |
d196bd880 env_mmc: add supp... |
292 |
#endif /* CONFIG_ENV_OFFSET_REDUND */ |