blob: 71dcc4c3e2547c54e104dc0ac10fac802b7a54b5 [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 Wen9f84f212010-11-10 07:39:23 +080032#include <search.h>
Lei Wenff833ed2010-10-13 11:07:21 +080033#include <errno.h>
Terry Lvb4eceac2010-05-17 10:57:01 +080034
35/* references to names in env_common.c */
36extern uchar default_environment[];
37
38char *env_name_spec = "MMC";
39
40#ifdef ENV_IS_EMBEDDED
41extern uchar environment[];
42env_t *env_ptr = (env_t *)(&environment[0]);
43#else /* ! ENV_IS_EMBEDDED */
44env_t *env_ptr = NULL;
45#endif /* ENV_IS_EMBEDDED */
46
47/* local functions */
48#if !defined(ENV_IS_EMBEDDED)
49static void use_default(void);
50#endif
51
52DECLARE_GLOBAL_DATA_PTR;
53
54uchar env_get_char_spec(int index)
55{
56 return *((uchar *)(gd->env_addr + index));
57}
58
59int env_init(void)
60{
61 /* use default */
62 gd->env_addr = (ulong)&default_environment[0];
63 gd->env_valid = 1;
64
65 return 0;
66}
67
68int init_mmc_for_env(struct mmc *mmc)
69{
70 if (!mmc) {
71 puts("No MMC card found\n");
72 return -1;
73 }
74
75 if (mmc_init(mmc)) {
76 puts("MMC init failed\n");
77 return -1;
78 }
79
80 return 0;
81}
82
83#ifdef CONFIG_CMD_SAVEENV
84
85inline int write_env(struct mmc *mmc, unsigned long size,
86 unsigned long offset, const void *buffer)
87{
88 uint blk_start, blk_cnt, n;
89
90 blk_start = ALIGN(offset, mmc->write_bl_len) / mmc->write_bl_len;
91 blk_cnt = ALIGN(size, mmc->write_bl_len) / mmc->write_bl_len;
92
93 n = mmc->block_dev.block_write(CONFIG_SYS_MMC_ENV_DEV, blk_start,
94 blk_cnt, (u_char *)buffer);
95
96 return (n == blk_cnt) ? 0 : -1;
97}
98
99int saveenv(void)
100{
Lei Wenff833ed2010-10-13 11:07:21 +0800101 env_t env_new;
102 ssize_t len;
103 char *res;
Terry Lvb4eceac2010-05-17 10:57:01 +0800104 struct mmc *mmc = find_mmc_device(CONFIG_SYS_MMC_ENV_DEV);
105
106 if (init_mmc_for_env(mmc))
107 return 1;
108
Lei Wenff833ed2010-10-13 11:07:21 +0800109 res = (char *)&env_new.data;
Mike Frysinger92d7a992010-12-08 06:26:04 -0500110 len = hexport_r(&env_htab, '\0', &res, ENV_SIZE);
Lei Wenff833ed2010-10-13 11:07:21 +0800111 if (len < 0) {
112 error("Cannot export environment: errno = %d\n", errno);
113 return 1;
114 }
115 env_new.crc = crc32(0, env_new.data, ENV_SIZE);
Terry Lvb4eceac2010-05-17 10:57:01 +0800116 printf("Writing to MMC(%d)... ", CONFIG_SYS_MMC_ENV_DEV);
Lei Wenff833ed2010-10-13 11:07:21 +0800117 if (write_env(mmc, CONFIG_ENV_SIZE, CONFIG_ENV_OFFSET, (u_char *)&env_new)) {
Terry Lvb4eceac2010-05-17 10:57:01 +0800118 puts("failed\n");
119 return 1;
120 }
121
122 puts("done\n");
123 return 0;
124}
125#endif /* CONFIG_CMD_SAVEENV */
126
127inline int read_env(struct mmc *mmc, unsigned long size,
128 unsigned long offset, const void *buffer)
129{
130 uint blk_start, blk_cnt, n;
131
132 blk_start = ALIGN(offset, mmc->read_bl_len) / mmc->read_bl_len;
133 blk_cnt = ALIGN(size, mmc->read_bl_len) / mmc->read_bl_len;
134
135 n = mmc->block_dev.block_read(CONFIG_SYS_MMC_ENV_DEV, blk_start,
136 blk_cnt, (uchar *)buffer);
137
138 return (n == blk_cnt) ? 0 : -1;
139}
140
141void env_relocate_spec(void)
142{
143#if !defined(ENV_IS_EMBEDDED)
Steve Sakomana93ec572010-10-11 05:51:39 -0700144 char buf[CONFIG_ENV_SIZE];
145
Terry Lvb4eceac2010-05-17 10:57:01 +0800146 struct mmc *mmc = find_mmc_device(CONFIG_SYS_MMC_ENV_DEV);
147
Steve Sakomana93ec572010-10-11 05:51:39 -0700148 if (init_mmc_for_env(mmc)) {
149 use_default();
Terry Lvb4eceac2010-05-17 10:57:01 +0800150 return;
Steve Sakomana93ec572010-10-11 05:51:39 -0700151 }
Terry Lvb4eceac2010-05-17 10:57:01 +0800152
Steve Sakomana93ec572010-10-11 05:51:39 -0700153 if (read_env(mmc, CONFIG_ENV_SIZE, CONFIG_ENV_OFFSET, buf)) {
154 use_default();
155 return;
156 }
Terry Lvb4eceac2010-05-17 10:57:01 +0800157
Steve Sakomana93ec572010-10-11 05:51:39 -0700158 env_import(buf, 1);
Terry Lvb4eceac2010-05-17 10:57:01 +0800159#endif
160}
161
162#if !defined(ENV_IS_EMBEDDED)
163static void use_default()
164{
Steve Sakoman0e657e82010-10-05 15:31:38 -0700165 set_default_env(NULL);
Terry Lvb4eceac2010-05-17 10:57:01 +0800166}
167#endif