]> git.sur5r.net Git - u-boot/blob - common/env_common.c
61c4be54d0ea28e22e0f937235d3b27483a60a67
[u-boot] / common / env_common.c
1 /*
2  * (C) Copyright 2000-2010
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
6  * Andreas Heppel <aheppel@sysgo.de>
7  *
8  * See file CREDITS for list of people who contributed to this
9  * project.
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License as
13  * published by the Free Software Foundation; either version 2 of
14  * the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
24  * MA 02111-1307 USA
25  */
26
27 #include <common.h>
28 #include <command.h>
29 #include <environment.h>
30 #include <linux/stddef.h>
31 #include <search.h>
32 #include <errno.h>
33 #include <malloc.h>
34
35 DECLARE_GLOBAL_DATA_PTR;
36
37 /************************************************************************
38  * Default settings to be used when no valid environment is found
39  */
40
41 const uchar default_environment[] = {
42 #ifdef  CONFIG_BOOTARGS
43         "bootargs="     CONFIG_BOOTARGS                 "\0"
44 #endif
45 #ifdef  CONFIG_BOOTCOMMAND
46         "bootcmd="      CONFIG_BOOTCOMMAND              "\0"
47 #endif
48 #ifdef  CONFIG_RAMBOOTCOMMAND
49         "ramboot="      CONFIG_RAMBOOTCOMMAND           "\0"
50 #endif
51 #ifdef  CONFIG_NFSBOOTCOMMAND
52         "nfsboot="      CONFIG_NFSBOOTCOMMAND           "\0"
53 #endif
54 #if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)
55         "bootdelay="    __stringify(CONFIG_BOOTDELAY)   "\0"
56 #endif
57 #if defined(CONFIG_BAUDRATE) && (CONFIG_BAUDRATE >= 0)
58         "baudrate="     __stringify(CONFIG_BAUDRATE)    "\0"
59 #endif
60 #ifdef  CONFIG_LOADS_ECHO
61         "loads_echo="   __stringify(CONFIG_LOADS_ECHO)  "\0"
62 #endif
63 #ifdef  CONFIG_ETHADDR
64         "ethaddr="      __stringify(CONFIG_ETHADDR)     "\0"
65 #endif
66 #ifdef  CONFIG_ETH1ADDR
67         "eth1addr="     __stringify(CONFIG_ETH1ADDR)    "\0"
68 #endif
69 #ifdef  CONFIG_ETH2ADDR
70         "eth2addr="     __stringify(CONFIG_ETH2ADDR)    "\0"
71 #endif
72 #ifdef  CONFIG_ETH3ADDR
73         "eth3addr="     __stringify(CONFIG_ETH3ADDR)    "\0"
74 #endif
75 #ifdef  CONFIG_ETH4ADDR
76         "eth4addr="     __stringify(CONFIG_ETH4ADDR)    "\0"
77 #endif
78 #ifdef  CONFIG_ETH5ADDR
79         "eth5addr="     __stringify(CONFIG_ETH5ADDR)    "\0"
80 #endif
81 #ifdef  CONFIG_ETHPRIME
82         "ethprime="     CONFIG_ETHPRIME                 "\0"
83 #endif
84 #ifdef  CONFIG_IPADDR
85         "ipaddr="       __stringify(CONFIG_IPADDR)      "\0"
86 #endif
87 #ifdef  CONFIG_SERVERIP
88         "serverip="     __stringify(CONFIG_SERVERIP)    "\0"
89 #endif
90 #ifdef  CONFIG_SYS_AUTOLOAD
91         "autoload="     CONFIG_SYS_AUTOLOAD             "\0"
92 #endif
93 #ifdef  CONFIG_PREBOOT
94         "preboot="      CONFIG_PREBOOT                  "\0"
95 #endif
96 #ifdef  CONFIG_ROOTPATH
97         "rootpath="     CONFIG_ROOTPATH                 "\0"
98 #endif
99 #ifdef  CONFIG_GATEWAYIP
100         "gatewayip="    __stringify(CONFIG_GATEWAYIP)   "\0"
101 #endif
102 #ifdef  CONFIG_NETMASK
103         "netmask="      __stringify(CONFIG_NETMASK)     "\0"
104 #endif
105 #ifdef  CONFIG_HOSTNAME
106         "hostname="     __stringify(CONFIG_HOSTNAME)    "\0"
107 #endif
108 #ifdef  CONFIG_BOOTFILE
109         "bootfile="     CONFIG_BOOTFILE                 "\0"
110 #endif
111 #ifdef  CONFIG_LOADADDR
112         "loadaddr="     __stringify(CONFIG_LOADADDR)    "\0"
113 #endif
114 #ifdef  CONFIG_CLOCKS_IN_MHZ
115         "clocks_in_mhz=1\0"
116 #endif
117 #if defined(CONFIG_PCI_BOOTDELAY) && (CONFIG_PCI_BOOTDELAY > 0)
118         "pcidelay="     __stringify(CONFIG_PCI_BOOTDELAY)"\0"
119 #endif
120 #ifdef  CONFIG_ENV_VARS_UBOOT_CONFIG
121         "arch="         CONFIG_SYS_ARCH                 "\0"
122         "cpu="          CONFIG_SYS_CPU                  "\0"
123         "board="        CONFIG_SYS_BOARD                "\0"
124 #ifdef CONFIG_SYS_VENDOR
125         "vendor="       CONFIG_SYS_VENDOR               "\0"
126 #endif
127 #ifdef CONFIG_SYS_SOC
128         "soc="          CONFIG_SYS_SOC                  "\0"
129 #endif
130 #endif
131 #ifdef  CONFIG_EXTRA_ENV_SETTINGS
132         CONFIG_EXTRA_ENV_SETTINGS
133 #endif
134         "\0"
135 };
136
137 struct hsearch_data env_htab = {
138         .apply = env_check_apply,
139 };
140
141 static uchar __env_get_char_spec(int index)
142 {
143         return *((uchar *)(gd->env_addr + index));
144 }
145 uchar env_get_char_spec(int)
146         __attribute__((weak, alias("__env_get_char_spec")));
147
148 static uchar env_get_char_init(int index)
149 {
150         /* if crc was bad, use the default environment */
151         if (gd->env_valid)
152                 return env_get_char_spec(index);
153         else
154                 return default_environment[index];
155 }
156
157 uchar env_get_char_memory(int index)
158 {
159         return *env_get_addr(index);
160 }
161
162 uchar env_get_char(int index)
163 {
164         /* if relocated to RAM */
165         if (gd->flags & GD_FLG_RELOC)
166                 return env_get_char_memory(index);
167         else
168                 return env_get_char_init(index);
169 }
170
171 const uchar *env_get_addr(int index)
172 {
173         if (gd->env_valid)
174                 return (uchar *)(gd->env_addr + index);
175         else
176                 return &default_environment[index];
177 }
178
179 void set_default_env(const char *s)
180 {
181         /*
182          * By default, do not apply changes as they will eventually
183          * be applied by someone else
184          */
185         int do_apply = 0;
186         if (sizeof(default_environment) > ENV_SIZE) {
187                 puts("*** Error - default environment is too large\n\n");
188                 return;
189         }
190
191         if (s) {
192                 if (*s == '!') {
193                         printf("*** Warning - %s, "
194                                 "using default environment\n\n",
195                                 s + 1);
196                 } else {
197                         /*
198                          * This set_to_default was explicitly asked for
199                          * by the user, as opposed to being a recovery
200                          * mechanism.  Therefore we check every single
201                          * variable and apply changes to the system
202                          * right away (e.g. baudrate, console).
203                          */
204                         do_apply = 1;
205                         puts(s);
206                 }
207         } else {
208                 puts("Using default environment\n\n");
209         }
210
211         if (himport_r(&env_htab, (char *)default_environment,
212                         sizeof(default_environment), '\0', 0,
213                         0, NULL, do_apply) == 0)
214                 error("Environment import failed: errno = %d\n", errno);
215
216         gd->flags |= GD_FLG_ENV_READY;
217 }
218
219
220 /* [re]set individual variables to their value in the default environment */
221 int set_default_vars(int nvars, char * const vars[])
222 {
223         /*
224          * Special use-case: import from default environment
225          * (and use \0 as a separator)
226          */
227         return himport_r(&env_htab, (const char *)default_environment,
228                                 sizeof(default_environment), '\0', H_NOCLEAR,
229                                 nvars, vars, 1 /* do_apply */);
230 }
231
232 #ifndef CONFIG_SPL_BUILD
233 /*
234  * Check if CRC is valid and (if yes) import the environment.
235  * Note that "buf" may or may not be aligned.
236  */
237 int env_import(const char *buf, int check)
238 {
239         env_t *ep = (env_t *)buf;
240
241         if (check) {
242                 uint32_t crc;
243
244                 memcpy(&crc, &ep->crc, sizeof(crc));
245
246                 if (crc32(0, ep->data, ENV_SIZE) != crc) {
247                         set_default_env("!bad CRC");
248                         return 0;
249                 }
250         }
251
252         if (himport_r(&env_htab, (char *)ep->data, ENV_SIZE, '\0', 0,
253                         0, NULL, 0 /* do_apply */)) {
254                 gd->flags |= GD_FLG_ENV_READY;
255                 return 1;
256         }
257
258         error("Cannot import environment: errno = %d\n", errno);
259
260         set_default_env("!import failed");
261
262         return 0;
263 }
264 #endif
265
266 void env_relocate(void)
267 {
268 #if defined(CONFIG_NEEDS_MANUAL_RELOC)
269         env_reloc();
270 #endif
271         if (gd->env_valid == 0) {
272 #if defined(CONFIG_ENV_IS_NOWHERE) || defined(CONFIG_SPL_BUILD)
273                 /* Environment not changable */
274                 set_default_env(NULL);
275 #else
276                 bootstage_error(BOOTSTAGE_ID_NET_CHECKSUM);
277                 set_default_env("!bad CRC");
278 #endif
279         } else {
280                 env_relocate_spec();
281         }
282 }
283
284 #if defined(CONFIG_AUTO_COMPLETE) && !defined(CONFIG_SPL_BUILD)
285 int env_complete(char *var, int maxv, char *cmdv[], int bufsz, char *buf)
286 {
287         ENTRY *match;
288         int found, idx;
289
290         idx = 0;
291         found = 0;
292         cmdv[0] = NULL;
293
294         while ((idx = hmatch_r(var, idx, &match, &env_htab))) {
295                 int vallen = strlen(match->key) + 1;
296
297                 if (found >= maxv - 2 || bufsz < vallen)
298                         break;
299
300                 cmdv[found++] = buf;
301                 memcpy(buf, match->key, vallen);
302                 buf += vallen;
303                 bufsz -= vallen;
304         }
305
306         qsort(cmdv, found, sizeof(cmdv[0]), strcmp_compar);
307
308         if (idx)
309                 cmdv[found++] = "...";
310
311         cmdv[found] = NULL;
312         return found;
313 }
314 #endif