cmd_source.c 4.58 KB
Newer Older
wdenk's avatar
wdenk committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
/*
 * (C) Copyright 2001
 * Kyle Harris, kharris@nexus-tech.net
 *
 * 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
 */

/*
25 26 27 28 29
 * The "source" command allows to define "script images", i. e. files
 * that contain command sequences that can be executed by the command
 * interpreter. It returns the exit status of the last command
 * executed from the script. This is very similar to running a shell
 * script in a UNIX shell, hence the name for the command.
wdenk's avatar
wdenk committed
30 31 32 33 34 35 36 37 38 39 40 41 42 43
 */

/* #define DEBUG */

#include <common.h>
#include <command.h>
#include <image.h>
#include <malloc.h>
#include <asm/byteorder.h>
#if defined(CONFIG_8xx)
#include <mpc8xx.h>
#endif

int
44
source (ulong addr, const char *fit_uname)
wdenk's avatar
wdenk committed
45
{
Wolfgang Denk's avatar
Wolfgang Denk committed
46
	ulong		len;
47 48 49 50 51 52 53 54 55
	image_header_t	*hdr;
	ulong		*data;
	int		verify;
#if defined(CONFIG_FIT)
	const void*	fit_hdr;
	int		noffset;
	const void	*fit_data;
	size_t		fit_len;
#endif
wdenk's avatar
wdenk committed
56

57
	verify = getenv_yesno ("verify");
wdenk's avatar
wdenk committed
58

59
	switch (genimg_get_format ((void *)addr)) {
60 61
	case IMAGE_FORMAT_LEGACY:
		hdr = (image_header_t *)addr;
wdenk's avatar
wdenk committed
62

63 64 65 66
		if (!image_check_magic (hdr)) {
			puts ("Bad magic number\n");
			return 1;
		}
wdenk's avatar
wdenk committed
67

68 69
		if (!image_check_hcrc (hdr)) {
			puts ("Bad header crc\n");
wdenk's avatar
wdenk committed
70 71 72
			return 1;
		}

73 74 75 76 77 78 79 80 81 82 83
		if (verify) {
			if (!image_check_dcrc (hdr)) {
				puts ("Bad data crc\n");
				return 1;
			}
		}

		if (!image_check_type (hdr, IH_TYPE_SCRIPT)) {
			puts ("Bad image type\n");
			return 1;
		}
wdenk's avatar
wdenk committed
84

85 86
		/* get length of script */
		data = (ulong *)image_get_data (hdr);
wdenk's avatar
wdenk committed
87

88
		if ((len = uimage_to_cpu (*data)) == 0) {
89 90 91
			puts ("Empty Script\n");
			return 1;
		}
92 93 94 95 96 97 98

		/*
		 * scripts are just multi-image files with one component, seek
		 * past the zero-terminated sequence of image lengths to get
		 * to the actual image data
		 */
		while (*data++);
99 100 101
		break;
#if defined(CONFIG_FIT)
	case IMAGE_FORMAT_FIT:
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
		if (fit_uname == NULL) {
			puts ("No FIT subimage unit name\n");
			return 1;
		}

		fit_hdr = (const void *)addr;
		if (!fit_check_format (fit_hdr)) {
			puts ("Bad FIT image format\n");
			return 1;
		}

		/* get script component image node offset */
		noffset = fit_image_get_node (fit_hdr, fit_uname);
		if (noffset < 0) {
			printf ("Can't find '%s' FIT subimage\n", fit_uname);
			return 1;
		}

		if (!fit_image_check_type (fit_hdr, noffset, IH_TYPE_SCRIPT)) {
			puts ("Not a image image\n");
			return 1;
		}

		/* verify integrity */
		if (verify) {
			if (!fit_image_check_hashes (fit_hdr, noffset)) {
				puts ("Bad Data Hash\n");
				return 1;
			}
		}

		/* get script subimage data address and length */
		if (fit_image_get_data (fit_hdr, noffset, &fit_data, &fit_len)) {
			puts ("Could not find script subimage data\n");
			return 1;
		}

		data = (ulong *)fit_data;
		len = (ulong)fit_len;
		break;
142 143
#endif
	default:
144
		puts ("Wrong image format for \"source\" command\n");
wdenk's avatar
wdenk committed
145 146 147
		return 1;
	}

148
	debug ("** Script length: %ld\n", len);
149
	return run_command_list((char *)data, len, 0);
wdenk's avatar
wdenk committed
150 151
}

wdenk's avatar
wdenk committed
152
/**************************************************/
153
#if defined(CONFIG_CMD_SOURCE)
wdenk's avatar
wdenk committed
154
int
155
do_source (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
wdenk's avatar
wdenk committed
156 157 158
{
	ulong addr;
	int rcode;
159
	const char *fit_uname = NULL;
wdenk's avatar
wdenk committed
160

161
	/* Find script image */
wdenk's avatar
wdenk committed
162
	if (argc < 2) {
163
		addr = CONFIG_SYS_LOAD_ADDR;
164
		debug ("*  source: default load address = 0x%08lx\n", addr);
165 166
#if defined(CONFIG_FIT)
	} else if (fit_parse_subimage (argv[1], load_addr, &addr, &fit_uname)) {
167
		debug ("*  source: subimage '%s' from FIT image at 0x%08lx\n",
168 169
				fit_uname, addr);
#endif
wdenk's avatar
wdenk committed
170
	} else {
171
		addr = simple_strtoul(argv[1], NULL, 16);
172
		debug ("*  source: cmdline image address = 0x%08lx\n", addr);
wdenk's avatar
wdenk committed
173 174
	}

175
	printf ("## Executing script at %08lx\n", addr);
176
	rcode = source (addr, fit_uname);
wdenk's avatar
wdenk committed
177 178
	return rcode;
}
wdenk's avatar
wdenk committed
179

180
U_BOOT_CMD(
181
	source, 2, 0,	do_source,
Peter Tyser's avatar
Peter Tyser committed
182
	"run script from memory",
183 184
	"[addr]\n"
	"\t- run script starting at addr\n"
185
	"\t- A valid image header must be present"
186
#if defined(CONFIG_FIT)
187
	"\n"
188
	"For FIT format uImage addr must include subimage\n"
189
	"unit name in the form of addr:<subimg_uname>"
190
#endif
191
);
192
#endif