Blame view
env/mmc.c
8.29 KB
83d290c56 SPDX: Convert all... |
1 |
// SPDX-License-Identifier: GPL-2.0+ |
a80603598 Save environment ... |
2 |
/* |
97039ab98 env_mmc: Allow bo... |
3 |
* (C) Copyright 2008-2011 Freescale Semiconductor, Inc. |
a80603598 Save environment ... |
4 5 6 7 8 9 10 11 |
*/ /* #define DEBUG */ #include <common.h> #include <command.h> #include <environment.h> |
f8b8a5546 env_mmc: configur... |
12 |
#include <fdtdec.h> |
a80603598 Save environment ... |
13 14 |
#include <linux/stddef.h> #include <malloc.h> |
cf92e05c0 Move ALLOC_CACHE_... |
15 |
#include <memalign.h> |
a80603598 Save environment ... |
16 |
#include <mmc.h> |
c9e87ba66 env: Save environ... |
17 |
#include <part.h> |
6d1d51b32 env_mmc: fix comp... |
18 |
#include <search.h> |
e79f48393 env_mmc: fix cann... |
19 |
#include <errno.h> |
a80603598 Save environment ... |
20 |
|
c9e87ba66 env: Save environ... |
21 22 |
#define __STR(X) #X #define STR(X) __STR(X) |
d196bd880 env_mmc: add supp... |
23 24 25 26 |
#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 ... |
27 |
DECLARE_GLOBAL_DATA_PTR; |
97039ab98 env_mmc: Allow bo... |
28 29 30 |
#if !defined(CONFIG_ENV_OFFSET) #define CONFIG_ENV_OFFSET 0 #endif |
f8b8a5546 env_mmc: configur... |
31 |
#if CONFIG_IS_ENABLED(OF_CONTROL) |
c9e87ba66 env: Save environ... |
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
static inline int mmc_offset_try_partition(const char *str, s64 *val) { disk_partition_t info; struct blk_desc *desc; int len, i, ret; ret = blk_get_device_by_str("mmc", STR(CONFIG_SYS_MMC_ENV_DEV), &desc); if (ret < 0) return (ret); for (i = 1;;i++) { ret = part_get_info(desc, i, &info); if (ret < 0) return ret; if (!strncmp((const char *)info.name, str, sizeof(str))) break; } /* round up to info.blksz */ len = (CONFIG_ENV_SIZE + info.blksz - 1) & ~(info.blksz - 1); /* use the top of the partion for the environment */ *val = (info.start + info.size - 1) - len / info.blksz; return 0; } |
f8b8a5546 env_mmc: configur... |
59 60 |
static inline s64 mmc_offset(int copy) { |
c9e87ba66 env: Save environ... |
61 62 63 64 65 66 67 68 69 |
const struct { const char *offset_redund; const char *partition; const char *offset; } dt_prop = { .offset_redund = "u-boot,mmc-env-offset-redundant", .partition = "u-boot,mmc-env-partition", .offset = "u-boot,mmc-env-offset", }; |
fd374665c env: suppress a s... |
70 |
s64 val = 0, defvalue; |
c9e87ba66 env: Save environ... |
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
const char *propname; const char *str; int err; /* look for the partition in mmc CONFIG_SYS_MMC_ENV_DEV */ str = fdtdec_get_config_string(gd->fdt_blob, dt_prop.partition); if (str) { /* try to place the environment at end of the partition */ err = mmc_offset_try_partition(str, &val); if (!err) return val; } defvalue = CONFIG_ENV_OFFSET; propname = dt_prop.offset; |
f8b8a5546 env_mmc: configur... |
86 87 88 |
#if defined(CONFIG_ENV_OFFSET_REDUND) if (copy) { |
f8b8a5546 env_mmc: configur... |
89 |
defvalue = CONFIG_ENV_OFFSET_REDUND; |
c9e87ba66 env: Save environ... |
90 |
propname = dt_prop.offset_redund; |
f8b8a5546 env_mmc: configur... |
91 92 |
} #endif |
f8b8a5546 env_mmc: configur... |
93 94 95 96 |
return fdtdec_get_config_int(gd->fdt_blob, propname, defvalue); } #else static inline s64 mmc_offset(int copy) |
97039ab98 env_mmc: Allow bo... |
97 |
{ |
f8b8a5546 env_mmc: configur... |
98 |
s64 offset = CONFIG_ENV_OFFSET; |
5c088ee84 env_mmc: allow ne... |
99 |
|
f8b8a5546 env_mmc: configur... |
100 |
#if defined(CONFIG_ENV_OFFSET_REDUND) |
d196bd880 env_mmc: add supp... |
101 |
if (copy) |
5c088ee84 env_mmc: allow ne... |
102 |
offset = CONFIG_ENV_OFFSET_REDUND; |
d196bd880 env_mmc: add supp... |
103 |
#endif |
f8b8a5546 env_mmc: configur... |
104 105 106 107 108 109 110 |
return offset; } #endif __weak int mmc_get_env_addr(struct mmc *mmc, int copy, u32 *env_addr) { s64 offset = mmc_offset(copy); |
5c088ee84 env_mmc: allow ne... |
111 112 113 114 115 |
if (offset < 0) offset += mmc->capacity; *env_addr = offset; |
97039ab98 env_mmc: Allow bo... |
116 117 |
return 0; } |
97039ab98 env_mmc: Allow bo... |
118 |
|
e92029c0f env_mmc: support ... |
119 120 121 122 |
__weak int mmc_get_env_dev(void) { return CONFIG_SYS_MMC_ENV_DEV; } |
b9c8ccaba env_mmc.c: Allow ... |
123 |
#ifdef CONFIG_SYS_MMC_ENV_PART |
6e7b7df4d env_mmc: support ... |
124 125 126 127 |
__weak uint mmc_get_env_part(struct mmc *mmc) { return CONFIG_SYS_MMC_ENV_PART; } |
873cc1d77 mmc: store hwpart... |
128 |
static unsigned char env_mmc_orig_hwpart; |
6e7b7df4d env_mmc: support ... |
129 130 131 |
static int mmc_set_env_part(struct mmc *mmc) { uint part = mmc_get_env_part(mmc); |
e92029c0f env_mmc: support ... |
132 |
int dev = mmc_get_env_dev(); |
6e7b7df4d env_mmc: support ... |
133 |
int ret = 0; |
b9c8ccaba env_mmc.c: Allow ... |
134 |
|
69f45cd53 dm: mmc: Use the ... |
135 136 |
env_mmc_orig_hwpart = mmc_get_blk_desc(mmc)->hwpart; ret = blk_select_hwpart_devnum(IF_TYPE_MMC, dev, part); |
873cc1d77 mmc: store hwpart... |
137 138 139 |
if (ret) puts("MMC partition switch failed "); |
6e7b7df4d env_mmc: support ... |
140 141 142 143 144 |
return ret; } #else static inline int mmc_set_env_part(struct mmc *mmc) {return 0; }; |
b9c8ccaba env_mmc.c: Allow ... |
145 |
#endif |
c75648d75 env_mmc: add erro... |
146 |
static const char *init_mmc_for_env(struct mmc *mmc) |
6e7b7df4d env_mmc: support ... |
147 |
{ |
c75648d75 env_mmc: add erro... |
148 |
if (!mmc) |
c5d548a9f env: common: acce... |
149 |
return "No MMC card found"; |
a80603598 Save environment ... |
150 |
|
d48b8d113 env: Properly che... |
151 |
#if CONFIG_IS_ENABLED(BLK) |
01b73fe63 dm: mmc: Ensure t... |
152 153 154 |
struct udevice *dev; if (blk_get_from_parent(mmc->dev, &dev)) |
c5d548a9f env: common: acce... |
155 |
return "No block device"; |
01b73fe63 dm: mmc: Ensure t... |
156 |
#else |
c75648d75 env_mmc: add erro... |
157 |
if (mmc_init(mmc)) |
c5d548a9f env: common: acce... |
158 |
return "MMC init failed"; |
e7017a3c7 dm: mmc: Don't re... |
159 |
#endif |
c75648d75 env_mmc: add erro... |
160 |
if (mmc_set_env_part(mmc)) |
c5d548a9f env: common: acce... |
161 |
return "MMC partition switch failed"; |
a80603598 Save environment ... |
162 |
|
c75648d75 env_mmc: add erro... |
163 |
return NULL; |
a80603598 Save environment ... |
164 |
} |
9404a5fc7 env_mmc: allow en... |
165 166 167 |
static void fini_mmc_for_env(struct mmc *mmc) { #ifdef CONFIG_SYS_MMC_ENV_PART |
e92029c0f env_mmc: support ... |
168 |
int dev = mmc_get_env_dev(); |
b9c8ccaba env_mmc.c: Allow ... |
169 |
|
69f45cd53 dm: mmc: Use the ... |
170 |
blk_select_hwpart_devnum(IF_TYPE_MMC, dev, env_mmc_orig_hwpart); |
9404a5fc7 env_mmc: allow en... |
171 172 |
#endif } |
e5bce247b env: Switch over ... |
173 |
#if defined(CONFIG_CMD_SAVEENV) && !defined(CONFIG_SPL_BUILD) |
e8db8f71c env: clean env_mm... |
174 175 |
static inline int write_env(struct mmc *mmc, unsigned long size, unsigned long offset, const void *buffer) |
a80603598 Save environment ... |
176 177 |
{ uint blk_start, blk_cnt, n; |
5461acba4 dm: env: mmc: Con... |
178 |
struct blk_desc *desc = mmc_get_blk_desc(mmc); |
a80603598 Save environment ... |
179 |
|
e8db8f71c env: clean env_mm... |
180 181 |
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 ... |
182 |
|
5461acba4 dm: env: mmc: Con... |
183 |
n = blk_dwrite(desc, blk_start, blk_cnt, (u_char *)buffer); |
a80603598 Save environment ... |
184 185 186 |
return (n == blk_cnt) ? 0 : -1; } |
e5bce247b env: Switch over ... |
187 |
static int env_mmc_save(void) |
a80603598 Save environment ... |
188 |
{ |
cd0f4fa1c Revert "env: fix ... |
189 |
ALLOC_CACHE_ALIGN_BUFFER(env_t, env_new, 1); |
e92029c0f env_mmc: support ... |
190 191 |
int dev = mmc_get_env_dev(); struct mmc *mmc = find_mmc_device(dev); |
e8db8f71c env: clean env_mm... |
192 |
u32 offset; |
d196bd880 env_mmc: add supp... |
193 |
int ret, copy = 0; |
c75648d75 env_mmc: add erro... |
194 |
const char *errmsg; |
a80603598 Save environment ... |
195 |
|
c75648d75 env_mmc: add erro... |
196 197 198 199 |
errmsg = init_mmc_for_env(mmc); if (errmsg) { printf("%s ", errmsg); |
97039ab98 env_mmc: Allow bo... |
200 |
return 1; |
c75648d75 env_mmc: add erro... |
201 |
} |
97039ab98 env_mmc: Allow bo... |
202 |
|
7ce1526ed env: Add env_expo... |
203 204 |
ret = env_export(env_new); if (ret) |
9404a5fc7 env_mmc: allow en... |
205 |
goto fini; |
d196bd880 env_mmc: add supp... |
206 207 |
#ifdef CONFIG_ENV_OFFSET_REDUND |
203e94f6c env: Add an enum ... |
208 |
if (gd->env_valid == ENV_VALID) |
d196bd880 env_mmc: add supp... |
209 210 211 212 213 214 215 |
copy = 1; #endif if (mmc_get_env_addr(mmc, copy, &offset)) { ret = 1; goto fini; } |
e92029c0f env_mmc: support ... |
216 |
printf("Writing to %sMMC(%d)... ", copy ? "redundant " : "", dev); |
4036b6301 env_mmc: align bu... |
217 |
if (write_env(mmc, CONFIG_ENV_SIZE, offset, (u_char *)env_new)) { |
a80603598 Save environment ... |
218 219 |
puts("failed "); |
9404a5fc7 env_mmc: allow en... |
220 221 |
ret = 1; goto fini; |
a80603598 Save environment ... |
222 |
} |
9404a5fc7 env_mmc: allow en... |
223 |
ret = 0; |
d196bd880 env_mmc: add supp... |
224 |
#ifdef CONFIG_ENV_OFFSET_REDUND |
203e94f6c env: Add an enum ... |
225 |
gd->env_valid = gd->env_valid == ENV_REDUND ? ENV_VALID : ENV_REDUND; |
d196bd880 env_mmc: add supp... |
226 |
#endif |
9404a5fc7 env_mmc: allow en... |
227 228 229 |
fini: fini_mmc_for_env(mmc); return ret; |
a80603598 Save environment ... |
230 |
} |
348539250 env: mmc: add era... |
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 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 |
#if defined(CONFIG_CMD_ERASEENV) static inline int erase_env(struct mmc *mmc, unsigned long size, unsigned long offset) { uint blk_start, blk_cnt, n; struct blk_desc *desc = mmc_get_blk_desc(mmc); blk_start = ALIGN(offset, mmc->write_bl_len) / mmc->write_bl_len; blk_cnt = ALIGN(size, mmc->write_bl_len) / mmc->write_bl_len; n = blk_derase(desc, blk_start, blk_cnt); printf("%d blocks erased: %s ", n, (n == blk_cnt) ? "OK" : "ERROR"); return (n == blk_cnt) ? 0 : 1; } static int env_mmc_erase(void) { int dev = mmc_get_env_dev(); struct mmc *mmc = find_mmc_device(dev); int ret, copy = 0; u32 offset; const char *errmsg; errmsg = init_mmc_for_env(mmc); if (errmsg) { printf("%s ", errmsg); return 1; } if (mmc_get_env_addr(mmc, copy, &offset)) return CMD_RET_FAILURE; ret = erase_env(mmc, CONFIG_ENV_SIZE, offset); #ifdef CONFIG_ENV_OFFSET_REDUND copy = 1; if (mmc_get_env_addr(mmc, copy, &offset)) return CMD_RET_FAILURE; ret |= erase_env(mmc, CONFIG_ENV_SIZE, offset); #endif return ret; } #endif /* CONFIG_CMD_ERASEENV */ |
e5bce247b env: Switch over ... |
281 |
#endif /* CONFIG_CMD_SAVEENV && !CONFIG_SPL_BUILD */ |
a80603598 Save environment ... |
282 |
|
e8db8f71c env: clean env_mm... |
283 284 |
static inline int read_env(struct mmc *mmc, unsigned long size, unsigned long offset, const void *buffer) |
a80603598 Save environment ... |
285 286 |
{ uint blk_start, blk_cnt, n; |
5461acba4 dm: env: mmc: Con... |
287 |
struct blk_desc *desc = mmc_get_blk_desc(mmc); |
a80603598 Save environment ... |
288 |
|
e8db8f71c env: clean env_mm... |
289 290 |
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 ... |
291 |
|
5461acba4 dm: env: mmc: Con... |
292 |
n = blk_dread(desc, blk_start, blk_cnt, (uchar *)buffer); |
a80603598 Save environment ... |
293 294 295 |
return (n == blk_cnt) ? 0 : -1; } |
d196bd880 env_mmc: add supp... |
296 |
#ifdef CONFIG_ENV_OFFSET_REDUND |
c59519919 env: Adjust the l... |
297 |
static int env_mmc_load(void) |
d196bd880 env_mmc: add supp... |
298 299 |
{ #if !defined(ENV_IS_EMBEDDED) |
b9c8ccaba env_mmc.c: Allow ... |
300 |
struct mmc *mmc; |
d196bd880 env_mmc: add supp... |
301 302 |
u32 offset1, offset2; int read1_fail = 0, read2_fail = 0; |
d196bd880 env_mmc: add supp... |
303 |
int ret; |
e92029c0f env_mmc: support ... |
304 |
int dev = mmc_get_env_dev(); |
c75648d75 env_mmc: add erro... |
305 |
const char *errmsg = NULL; |
d196bd880 env_mmc: add supp... |
306 |
|
452a2722e env_mmc: fix buff... |
307 308 |
ALLOC_CACHE_ALIGN_BUFFER(env_t, tmp_env1, 1); ALLOC_CACHE_ALIGN_BUFFER(env_t, tmp_env2, 1); |
26862b4a4 env: mmc/fat/ext4... |
309 |
mmc_initialize(NULL); |
b9c8ccaba env_mmc.c: Allow ... |
310 |
mmc = find_mmc_device(dev); |
c75648d75 env_mmc: add erro... |
311 312 |
errmsg = init_mmc_for_env(mmc); if (errmsg) { |
c59519919 env: Adjust the l... |
313 |
ret = -EIO; |
d196bd880 env_mmc: add supp... |
314 315 316 317 318 |
goto err; } if (mmc_get_env_addr(mmc, 0, &offset1) || mmc_get_env_addr(mmc, 1, &offset2)) { |
c59519919 env: Adjust the l... |
319 |
ret = -EIO; |
d196bd880 env_mmc: add supp... |
320 321 322 323 324 |
goto fini; } read1_fail = read_env(mmc, CONFIG_ENV_SIZE, offset1, tmp_env1); read2_fail = read_env(mmc, CONFIG_ENV_SIZE, offset2, tmp_env2); |
31f044bd9 env: move more co... |
325 326 |
ret = env_import_redund((char *)tmp_env1, read1_fail, (char *)tmp_env2, read2_fail); |
d196bd880 env_mmc: add supp... |
327 328 329 330 331 |
fini: fini_mmc_for_env(mmc); err: if (ret) |
c5d548a9f env: common: acce... |
332 |
set_default_env(errmsg, 0); |
c59519919 env: Adjust the l... |
333 |
|
d196bd880 env_mmc: add supp... |
334 |
#endif |
c59519919 env: Adjust the l... |
335 |
return ret; |
d196bd880 env_mmc: add supp... |
336 337 |
} #else /* ! CONFIG_ENV_OFFSET_REDUND */ |
c59519919 env: Adjust the l... |
338 |
static int env_mmc_load(void) |
a80603598 Save environment ... |
339 340 |
{ #if !defined(ENV_IS_EMBEDDED) |
cd0f4fa1c Revert "env: fix ... |
341 |
ALLOC_CACHE_ALIGN_BUFFER(char, buf, CONFIG_ENV_SIZE); |
b9c8ccaba env_mmc.c: Allow ... |
342 |
struct mmc *mmc; |
97039ab98 env_mmc: Allow bo... |
343 |
u32 offset; |
9404a5fc7 env_mmc: allow en... |
344 |
int ret; |
e92029c0f env_mmc: support ... |
345 |
int dev = mmc_get_env_dev(); |
c75648d75 env_mmc: add erro... |
346 |
const char *errmsg; |
b9c8ccaba env_mmc.c: Allow ... |
347 |
|
b9c8ccaba env_mmc.c: Allow ... |
348 |
mmc = find_mmc_device(dev); |
a80603598 Save environment ... |
349 |
|
c75648d75 env_mmc: add erro... |
350 351 |
errmsg = init_mmc_for_env(mmc); if (errmsg) { |
c59519919 env: Adjust the l... |
352 |
ret = -EIO; |
9404a5fc7 env_mmc: allow en... |
353 354 |
goto err; } |
a80603598 Save environment ... |
355 |
|
d196bd880 env_mmc: add supp... |
356 |
if (mmc_get_env_addr(mmc, 0, &offset)) { |
c59519919 env: Adjust the l... |
357 |
ret = -EIO; |
9404a5fc7 env_mmc: allow en... |
358 359 |
goto fini; } |
cd0f4fa1c Revert "env: fix ... |
360 |
if (read_env(mmc, CONFIG_ENV_SIZE, offset, buf)) { |
c75648d75 env_mmc: add erro... |
361 |
errmsg = "!read failed"; |
c59519919 env: Adjust the l... |
362 |
ret = -EIO; |
9404a5fc7 env_mmc: allow en... |
363 364 |
goto fini; } |
a80603598 Save environment ... |
365 |
|
2166ebf78 env: make env dri... |
366 |
ret = env_import(buf, 1); |
9404a5fc7 env_mmc: allow en... |
367 368 369 370 371 |
fini: fini_mmc_for_env(mmc); err: if (ret) |
c5d548a9f env: common: acce... |
372 |
set_default_env(errmsg, 0); |
a80603598 Save environment ... |
373 |
#endif |
c59519919 env: Adjust the l... |
374 |
return ret; |
a80603598 Save environment ... |
375 |
} |
d196bd880 env_mmc: add supp... |
376 |
#endif /* CONFIG_ENV_OFFSET_REDUND */ |
4415f1d1f env: Create a loc... |
377 378 379 |
U_BOOT_ENV_LOCATION(mmc) = { .location = ENVL_MMC, |
ac358beb8 env: Drop the env... |
380 |
ENV_NAME("MMC") |
e5bce247b env: Switch over ... |
381 |
.load = env_mmc_load, |
4415f1d1f env: Create a loc... |
382 |
#ifndef CONFIG_SPL_BUILD |
e5bce247b env: Switch over ... |
383 |
.save = env_save_ptr(env_mmc_save), |
348539250 env: mmc: add era... |
384 385 386 |
#if defined(CONFIG_CMD_ERASEENV) .erase = env_mmc_erase, #endif |
4415f1d1f env: Create a loc... |
387 |
#endif |
4415f1d1f env: Create a loc... |
388 |
}; |