blob: 3d7fceb099d4ee3913eb99c720e23249801fc78b [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>
Lei Wenff833ed2010-10-13 11:07:21 +080032#include <errno.h>
Terry Lvb4eceac2010-05-17 10:57:01 +080033
34/* references to names in env_common.c */
35extern uchar default_environment[];
36
37char *env_name_spec = "MMC";
38
39#ifdef ENV_IS_EMBEDDED
40extern uchar environment[];
41env_t *env_ptr = (env_t *)(&environment[0]);
42#else /* ! ENV_IS_EMBEDDED */
43env_t *env_ptr = NULL;
44#endif /* ENV_IS_EMBEDDED */
45
46/* local functions */
47#if !defined(ENV_IS_EMBEDDED)
48static void use_default(void);
49#endif
50
51DECLARE_GLOBAL_DATA_PTR;
52
53uchar env_get_char_spec(int index)
54{
55 return *((uchar *)(gd->env_addr + index));
56}
57
58int env_init(void)
59{
60 /* use default */
61 gd->env_addr = (ulong)&default_environment[0];
62 gd->env_valid = 1;
63
64 return 0;
65}
66
67int init_mmc_for_env(struct mmc *mmc)
68{
69 if (!mmc) {
70 puts("No MMC card found\n");
71 return -1;
72 }
73
74 if (mmc_init(mmc)) {
75 puts("MMC init failed\n");
76 return -1;
77 }
78
79 return 0;
80}
81
82#ifdef CONFIG_CMD_SAVEENV
83
84inline int write_env(struct mmc *mmc, unsigned long size,
85 unsigned long offset, const void *buffer)
86{
87 uint blk_start, blk_cnt, n;
88
89 blk_start = ALIGN(offset, mmc->write_bl_len) / mmc->write_bl_len;
90 blk_cnt = ALIGN(size, mmc->write_bl_len) / mmc->write_bl_len;
91
92 n = mmc->block_dev.block_write(CONFIG_SYS_MMC_ENV_DEV, blk_start,
93 blk_cnt, (u_char *)buffer);
94
95 return (n == blk_cnt) ? 0 : -1;
96}
97
98int saveenv(void)
99{
Lei Wenff833ed2010-10-13 11:07:21 +0800100 env_t env_new;
101 ssize_t len;
102 char *res;
Terry Lvb4eceac2010-05-17 10:57:01 +0800103 struct mmc *mmc = find_mmc_device(CONFIG_SYS_MMC_ENV_DEV);
104
105 if (init_mmc_for_env(mmc))
106 return 1;
107
Lei Wenff833ed2010-10-13 11:07:21 +0800108 res = (char *)&env_new.data;
109 len = hexport('\0', &res, ENV_SIZE);
110 if (len < 0) {
111 error("Cannot export environment: errno = %d\n", errno);
112 return 1;
113 }
114 env_new.crc = crc32(0, env_new.data, ENV_SIZE);
Terry Lvb4eceac2010-05-17 10:57:01 +0800115 printf("Writing to MMC(%d)... ", CONFIG_SYS_MMC_ENV_DEV);
Lei Wenff833ed2010-10-13 11:07:21 +0800116 if (write_env(mmc, CONFIG_ENV_SIZE, CONFIG_ENV_OFFSET, (u_char *)&env_new)) {
Terry Lvb4eceac2010-05-17 10:57:01 +0800117 puts("failed\n");
118 return 1;
119 }
120
121 puts("done\n");
122 return 0;
123}
124#endif /* CONFIG_CMD_SAVEENV */
125
126inline int read_env(struct mmc *mmc, unsigned long size,
127 unsigned long offset, const void *buffer)
128{
129 uint blk_start, blk_cnt, n;
130
131 blk_start = ALIGN(offset, mmc->read_bl_len) / mmc->read_bl_len;
132 blk_cnt = ALIGN(size, mmc->read_bl_len) / mmc->read_bl_len;
133
134 n = mmc->block_dev.block_read(CONFIG_SYS_MMC_ENV_DEV, blk_start,
135 blk_cnt, (uchar *)buffer);
136
137 return (n == blk_cnt) ? 0 : -1;
138}
139
140void env_relocate_spec(void)
141{
142#if !defined(ENV_IS_EMBEDDED)
Steve Sakomana93ec572010-10-11 05:51:39 -0700143 char buf[CONFIG_ENV_SIZE];
144
Terry Lvb4eceac2010-05-17 10:57:01 +0800145 struct mmc *mmc = find_mmc_device(CONFIG_SYS_MMC_ENV_DEV);
146
Steve Sakomana93ec572010-10-11 05:51:39 -0700147 if (init_mmc_for_env(mmc)) {
148 use_default();
Terry Lvb4eceac2010-05-17 10:57:01 +0800149 return;
Steve Sakomana93ec572010-10-11 05:51:39 -0700150 }
Terry Lvb4eceac2010-05-17 10:57:01 +0800151
Steve Sakomana93ec572010-10-11 05:51:39 -0700152 if (read_env(mmc, CONFIG_ENV_SIZE, CONFIG_ENV_OFFSET, buf)) {
153 use_default();
154 return;
155 }
Terry Lvb4eceac2010-05-17 10:57:01 +0800156
Steve Sakomana93ec572010-10-11 05:51:39 -0700157 env_import(buf, 1);
Terry Lvb4eceac2010-05-17 10:57:01 +0800158#endif
159}
160
161#if !defined(ENV_IS_EMBEDDED)
162static void use_default()
163{
Steve Sakoman0e657e82010-10-05 15:31:38 -0700164 set_default_env(NULL);
Terry Lvb4eceac2010-05-17 10:57:01 +0800165}
166#endif