blob: cc288d487c2e0d7d05df001154d1e4470d47fb74 [file] [log] [blame]
Terry Lvb4eceac2010-05-17 10:57:01 +08001/*
2 * (C) Copyright 2008-2010 Freescale Semiconductor, Inc.
3 *
4 * See file CREDITS for list of people who contributed to this
5 * project.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of
10 * the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
20 * MA 02111-1307 USA
21 */
22
23/* #define DEBUG */
24
25#include <common.h>
26
27#include <command.h>
28#include <environment.h>
29#include <linux/stddef.h>
30#include <malloc.h>
31#include <mmc.h>
32
33/* references to names in env_common.c */
34extern uchar default_environment[];
35
36char *env_name_spec = "MMC";
37
38#ifdef ENV_IS_EMBEDDED
39extern uchar environment[];
40env_t *env_ptr = (env_t *)(&environment[0]);
41#else /* ! ENV_IS_EMBEDDED */
42env_t *env_ptr = NULL;
43#endif /* ENV_IS_EMBEDDED */
44
45/* local functions */
46#if !defined(ENV_IS_EMBEDDED)
47static void use_default(void);
48#endif
49
50DECLARE_GLOBAL_DATA_PTR;
51
52uchar env_get_char_spec(int index)
53{
54 return *((uchar *)(gd->env_addr + index));
55}
56
57int env_init(void)
58{
59 /* use default */
60 gd->env_addr = (ulong)&default_environment[0];
61 gd->env_valid = 1;
62
63 return 0;
64}
65
66int init_mmc_for_env(struct mmc *mmc)
67{
68 if (!mmc) {
69 puts("No MMC card found\n");
70 return -1;
71 }
72
73 if (mmc_init(mmc)) {
74 puts("MMC init failed\n");
75 return -1;
76 }
77
78 return 0;
79}
80
81#ifdef CONFIG_CMD_SAVEENV
82
83inline int write_env(struct mmc *mmc, unsigned long size,
84 unsigned long offset, const void *buffer)
85{
86 uint blk_start, blk_cnt, n;
87
88 blk_start = ALIGN(offset, mmc->write_bl_len) / mmc->write_bl_len;
89 blk_cnt = ALIGN(size, mmc->write_bl_len) / mmc->write_bl_len;
90
91 n = mmc->block_dev.block_write(CONFIG_SYS_MMC_ENV_DEV, blk_start,
92 blk_cnt, (u_char *)buffer);
93
94 return (n == blk_cnt) ? 0 : -1;
95}
96
97int saveenv(void)
98{
99 struct mmc *mmc = find_mmc_device(CONFIG_SYS_MMC_ENV_DEV);
100
101 if (init_mmc_for_env(mmc))
102 return 1;
103
104 printf("Writing to MMC(%d)... ", CONFIG_SYS_MMC_ENV_DEV);
105 if (write_env(mmc, CONFIG_ENV_SIZE, CONFIG_ENV_OFFSET, env_ptr)) {
106 puts("failed\n");
107 return 1;
108 }
109
110 puts("done\n");
111 return 0;
112}
113#endif /* CONFIG_CMD_SAVEENV */
114
115inline int read_env(struct mmc *mmc, unsigned long size,
116 unsigned long offset, const void *buffer)
117{
118 uint blk_start, blk_cnt, n;
119
120 blk_start = ALIGN(offset, mmc->read_bl_len) / mmc->read_bl_len;
121 blk_cnt = ALIGN(size, mmc->read_bl_len) / mmc->read_bl_len;
122
123 n = mmc->block_dev.block_read(CONFIG_SYS_MMC_ENV_DEV, blk_start,
124 blk_cnt, (uchar *)buffer);
125
126 return (n == blk_cnt) ? 0 : -1;
127}
128
129void env_relocate_spec(void)
130{
131#if !defined(ENV_IS_EMBEDDED)
132 struct mmc *mmc = find_mmc_device(CONFIG_SYS_MMC_ENV_DEV);
133
134 if (init_mmc_for_env(mmc))
135 return;
136
137 if (read_env(mmc, CONFIG_ENV_SIZE, CONFIG_ENV_OFFSET, env_ptr))
138 return use_default();
139
140 if (crc32(0, env_ptr->data, ENV_SIZE) != env_ptr->crc)
141 return use_default();
142
143 gd->env_valid = 1;
144#endif
145}
146
147#if !defined(ENV_IS_EMBEDDED)
148static void use_default()
149{
Steve Sakoman0e657e82010-10-05 15:31:38 -0700150 set_default_env(NULL);
Terry Lvb4eceac2010-05-17 10:57:01 +0800151}
152#endif