env_common.c 6.31 KB
Newer Older
wdenk's avatar
wdenk committed
1
/*
2
 * (C) Copyright 2000-2010
wdenk's avatar
wdenk committed
3 4 5 6
 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
 *
 * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
 * Andreas Heppel <aheppel@sysgo.de>
7
 *
wdenk's avatar
wdenk committed
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
 * See file CREDITS for list of people who contributed to this
 * project.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307 USA
 */

#include <common.h>
#include <command.h>
#include <environment.h>
#include <linux/stddef.h>
31 32
#include <search.h>
#include <errno.h>
wdenk's avatar
wdenk committed
33 34
#include <malloc.h>

35 36
DECLARE_GLOBAL_DATA_PTR;

wdenk's avatar
wdenk committed
37 38 39 40 41 42
/************************************************************************
 * Default settings to be used when no valid environment is found
 */
#define XMK_STR(x)	#x
#define MK_STR(x)	XMK_STR(x)

Mike Frysinger's avatar
Mike Frysinger committed
43
const uchar default_environment[] = {
wdenk's avatar
wdenk committed
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
#ifdef	CONFIG_BOOTARGS
	"bootargs="	CONFIG_BOOTARGS			"\0"
#endif
#ifdef	CONFIG_BOOTCOMMAND
	"bootcmd="	CONFIG_BOOTCOMMAND		"\0"
#endif
#ifdef	CONFIG_RAMBOOTCOMMAND
	"ramboot="	CONFIG_RAMBOOTCOMMAND		"\0"
#endif
#ifdef	CONFIG_NFSBOOTCOMMAND
	"nfsboot="	CONFIG_NFSBOOTCOMMAND		"\0"
#endif
#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)
	"bootdelay="	MK_STR(CONFIG_BOOTDELAY)	"\0"
#endif
#if defined(CONFIG_BAUDRATE) && (CONFIG_BAUDRATE >= 0)
	"baudrate="	MK_STR(CONFIG_BAUDRATE)		"\0"
#endif
#ifdef	CONFIG_LOADS_ECHO
	"loads_echo="	MK_STR(CONFIG_LOADS_ECHO)	"\0"
#endif
#ifdef	CONFIG_ETHADDR
	"ethaddr="	MK_STR(CONFIG_ETHADDR)		"\0"
#endif
#ifdef	CONFIG_ETH1ADDR
	"eth1addr="	MK_STR(CONFIG_ETH1ADDR)		"\0"
#endif
#ifdef	CONFIG_ETH2ADDR
	"eth2addr="	MK_STR(CONFIG_ETH2ADDR)		"\0"
#endif
74 75 76
#ifdef	CONFIG_ETH3ADDR
	"eth3addr="	MK_STR(CONFIG_ETH3ADDR)		"\0"
#endif
77 78 79 80 81 82
#ifdef	CONFIG_ETH4ADDR
	"eth4addr="	MK_STR(CONFIG_ETH4ADDR)		"\0"
#endif
#ifdef	CONFIG_ETH5ADDR
	"eth5addr="	MK_STR(CONFIG_ETH5ADDR)		"\0"
#endif
wdenk's avatar
wdenk committed
83 84 85 86 87 88
#ifdef	CONFIG_IPADDR
	"ipaddr="	MK_STR(CONFIG_IPADDR)		"\0"
#endif
#ifdef	CONFIG_SERVERIP
	"serverip="	MK_STR(CONFIG_SERVERIP)		"\0"
#endif
89
#ifdef	CONFIG_SYS_AUTOLOAD
90
	"autoload="	CONFIG_SYS_AUTOLOAD		"\0"
wdenk's avatar
wdenk committed
91 92 93 94 95
#endif
#ifdef	CONFIG_PREBOOT
	"preboot="	CONFIG_PREBOOT			"\0"
#endif
#ifdef	CONFIG_ROOTPATH
96
	"rootpath="	CONFIG_ROOTPATH			"\0"
wdenk's avatar
wdenk committed
97 98 99 100 101 102 103 104 105 106 107
#endif
#ifdef	CONFIG_GATEWAYIP
	"gatewayip="	MK_STR(CONFIG_GATEWAYIP)	"\0"
#endif
#ifdef	CONFIG_NETMASK
	"netmask="	MK_STR(CONFIG_NETMASK)		"\0"
#endif
#ifdef	CONFIG_HOSTNAME
	"hostname="	MK_STR(CONFIG_HOSTNAME)		"\0"
#endif
#ifdef	CONFIG_BOOTFILE
108
	"bootfile="	CONFIG_BOOTFILE			"\0"
wdenk's avatar
wdenk committed
109 110 111 112
#endif
#ifdef	CONFIG_LOADADDR
	"loadaddr="	MK_STR(CONFIG_LOADADDR)		"\0"
#endif
113
#ifdef	CONFIG_CLOCKS_IN_MHZ
wdenk's avatar
wdenk committed
114 115
	"clocks_in_mhz=1\0"
#endif
116 117 118
#if defined(CONFIG_PCI_BOOTDELAY) && (CONFIG_PCI_BOOTDELAY > 0)
	"pcidelay="	MK_STR(CONFIG_PCI_BOOTDELAY)	"\0"
#endif
119 120 121 122 123 124 125 126 127 128 129
#ifdef	CONFIG_ENV_VARS_UBOOT_CONFIG
	"arch="		CONFIG_SYS_ARCH			"\0"
	"cpu="		CONFIG_SYS_CPU			"\0"
	"board="	CONFIG_SYS_BOARD		"\0"
#ifdef CONFIG_SYS_VENDOR
	"vendor="	CONFIG_SYS_VENDOR		"\0"
#endif
#ifdef CONFIG_SYS_SOC
	"soc="		CONFIG_SYS_SOC			"\0"
#endif
#endif
130
#ifdef	CONFIG_EXTRA_ENV_SETTINGS
wdenk's avatar
wdenk committed
131 132 133 134 135
	CONFIG_EXTRA_ENV_SETTINGS
#endif
	"\0"
};

136 137
struct hsearch_data env_htab;

138 139 140 141 142 143 144
static uchar __env_get_char_spec(int index)
{
	return *((uchar *)(gd->env_addr + index));
}
uchar env_get_char_spec(int)
	__attribute__((weak, alias("__env_get_char_spec")));

145
static uchar env_get_char_init(int index)
wdenk's avatar
wdenk committed
146 147 148
{
	/* if crc was bad, use the default environment */
	if (gd->env_valid)
149
		return env_get_char_spec(index);
150
	else
151
		return default_environment[index];
wdenk's avatar
wdenk committed
152 153
}

154
uchar env_get_char_memory(int index)
wdenk's avatar
wdenk committed
155
{
156
	return *env_get_addr(index);
wdenk's avatar
wdenk committed
157 158
}

159
uchar env_get_char(int index)
160 161 162
{
	/* if relocated to RAM */
	if (gd->flags & GD_FLG_RELOC)
163
		return env_get_char_memory(index);
164
	else
165
		return env_get_char_init(index);
166 167
}

168
const uchar *env_get_addr(int index)
wdenk's avatar
wdenk committed
169
{
170 171 172 173
	if (gd->env_valid)
		return (uchar *)(gd->env_addr + index);
	else
		return &default_environment[index];
wdenk's avatar
wdenk committed
174 175
}

176
void set_default_env(const char *s)
177 178
{
	if (sizeof(default_environment) > ENV_SIZE) {
179
		puts("*** Error - default environment is too large\n\n");
180 181 182
		return;
	}

183 184 185 186
	if (s) {
		if (*s == '!') {
			printf("*** Warning - %s, "
				"using default environment\n\n",
187
				s + 1);
188 189 190 191 192 193 194
		} else {
			puts(s);
		}
	} else {
		puts("Using default environment\n\n");
	}

195
	if (himport_r(&env_htab, (char *)default_environment,
196
			sizeof(default_environment), '\0', 0) == 0)
197
		error("Environment import failed: errno = %d\n", errno);
198

199
	gd->flags |= GD_FLG_ENV_READY;
200 201
}

202 203 204 205 206
/*
 * Check if CRC is valid and (if yes) import the environment.
 * Note that "buf" may or may not be aligned.
 */
int env_import(const char *buf, int check)
wdenk's avatar
wdenk committed
207
{
208
	env_t *ep = (env_t *)buf;
wdenk's avatar
wdenk committed
209

210 211 212 213 214 215 216 217 218 219 220
	if (check) {
		uint32_t crc;

		memcpy(&crc, &ep->crc, sizeof(crc));

		if (crc32(0, ep->data, ENV_SIZE) != crc) {
			set_default_env("!bad CRC");
			return 0;
		}
	}

221
	if (himport_r(&env_htab, (char *)ep->data, ENV_SIZE, '\0', 0)) {
222 223 224
		gd->flags |= GD_FLG_ENV_READY;
		return 1;
	}
wdenk's avatar
wdenk committed
225

226 227 228 229 230 231 232
	error("Cannot import environment: errno = %d\n", errno);

	set_default_env("!import failed");

	return 0;
}

233
void env_relocate(void)
234
{
235
#if defined(CONFIG_NEEDS_MANUAL_RELOC)
236 237
	env_reloc();
#endif
wdenk's avatar
wdenk committed
238
	if (gd->env_valid == 0) {
239
#if defined(CONFIG_ENV_IS_NOWHERE)	/* Environment not changable */
240
		set_default_env(NULL);
wdenk's avatar
wdenk committed
241
#else
242
		bootstage_error(BOOTSTAGE_ID_NET_CHECKSUM);
243
		set_default_env("!bad CRC");
244
#endif
245
	} else {
246
		env_relocate_spec();
wdenk's avatar
wdenk committed
247 248
	}
}
249

250
#ifdef CONFIG_AUTO_COMPLETE
251 252
int env_complete(char *var, int maxv, char *cmdv[], int bufsz, char *buf)
{
253 254
	ENTRY *match;
	int found, idx;
255

256
	idx = 0;
257 258 259
	found = 0;
	cmdv[0] = NULL;

260 261
	while ((idx = hmatch_r(var, idx, &match, &env_htab))) {
		int vallen = strlen(match->key) + 1;
262

263
		if (found >= maxv - 2 || bufsz < vallen)
264
			break;
265

266
		cmdv[found++] = buf;
267 268 269
		memcpy(buf, match->key, vallen);
		buf += vallen;
		bufsz -= vallen;
270 271
	}

272 273 274 275
	qsort(cmdv, found, sizeof(cmdv[0]), strcmp_compar);

	if (idx)
		cmdv[found++] = "...";
276

277 278 279 280
	cmdv[found] = NULL;
	return found;
}
#endif