1 /*
2  * (C) Copyright 2001
3  * Kyle Harris, kharris@nexus-tech.net
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  */
23 
24 /*
25  * The "source" command allows to define "script images", i. e. files
26  * that contain command sequences that can be executed by the command
27  * interpreter. It returns the exit status of the last command
28  * executed from the script. This is very similar to running a shell
29  * script in a UNIX shell, hence the name for the command.
30  */
31 
32 /* #define DEBUG */
33 
34 #include <common.h>
35 #include <command.h>
36 #include <image.h>
37 #include <malloc.h>
38 #include <asm/byteorder.h>
39 #if defined(CONFIG_8xx)
40 #include <mpc8xx.h>
41 #endif
42 #ifdef CONFIG_SYS_HUSH_PARSER
43 #include <hush.h>
44 #endif
45 
46 int
source(ulong addr,const char * fit_uname)47 source (ulong addr, const char *fit_uname)
48 {
49 	ulong		len;
50 	image_header_t	*hdr;
51 	ulong		*data;
52 	char		*cmd;
53 	int		rcode = 0;
54 	int		verify;
55 #if defined(CONFIG_FIT)
56 	const void*	fit_hdr;
57 	int		noffset;
58 	const void	*fit_data;
59 	size_t		fit_len;
60 #endif
61 
62 	verify = getenv_yesno ("verify");
63 
64 	switch (genimg_get_format ((void *)addr)) {
65 	case IMAGE_FORMAT_LEGACY:
66 		hdr = (image_header_t *)addr;
67 
68 		if (!image_check_magic (hdr)) {
69 			puts ("Bad magic number\n");
70 			return 1;
71 		}
72 
73 		if (!image_check_hcrc (hdr)) {
74 			puts ("Bad header crc\n");
75 			return 1;
76 		}
77 
78 		if (verify) {
79 			if (!image_check_dcrc (hdr)) {
80 				puts ("Bad data crc\n");
81 				return 1;
82 			}
83 		}
84 
85 		if (!image_check_type (hdr, IH_TYPE_SCRIPT)) {
86 			puts ("Bad image type\n");
87 			return 1;
88 		}
89 
90 		/* get length of script */
91 		data = (ulong *)image_get_data (hdr);
92 
93 		if ((len = uimage_to_cpu (*data)) == 0) {
94 			puts ("Empty Script\n");
95 			return 1;
96 		}
97 
98 		/*
99 		 * scripts are just multi-image files with one component, seek
100 		 * past the zero-terminated sequence of image lengths to get
101 		 * to the actual image data
102 		 */
103 		while (*data++);
104 		break;
105 #if defined(CONFIG_FIT)
106 	case IMAGE_FORMAT_FIT:
107 		if (fit_uname == NULL) {
108 			puts ("No FIT subimage unit name\n");
109 			return 1;
110 		}
111 
112 		fit_hdr = (const void *)addr;
113 		if (!fit_check_format (fit_hdr)) {
114 			puts ("Bad FIT image format\n");
115 			return 1;
116 		}
117 
118 		/* get script component image node offset */
119 		noffset = fit_image_get_node (fit_hdr, fit_uname);
120 		if (noffset < 0) {
121 			printf ("Can't find '%s' FIT subimage\n", fit_uname);
122 			return 1;
123 		}
124 
125 		if (!fit_image_check_type (fit_hdr, noffset, IH_TYPE_SCRIPT)) {
126 			puts ("Not a image image\n");
127 			return 1;
128 		}
129 
130 		/* verify integrity */
131 		if (verify) {
132 			if (!fit_image_check_hashes (fit_hdr, noffset)) {
133 				puts ("Bad Data Hash\n");
134 				return 1;
135 			}
136 		}
137 
138 		/* get script subimage data address and length */
139 		if (fit_image_get_data (fit_hdr, noffset, &fit_data, &fit_len)) {
140 			puts ("Could not find script subimage data\n");
141 			return 1;
142 		}
143 
144 		data = (ulong *)fit_data;
145 		len = (ulong)fit_len;
146 		break;
147 #endif
148 	default:
149 		puts ("Wrong image format for \"source\" command\n");
150 		return 1;
151 	}
152 
153 	debug ("** Script length: %ld\n", len);
154 
155 	if ((cmd = malloc (len + 1)) == NULL) {
156 		return 1;
157 	}
158 
159 	/* make sure cmd is null terminated */
160 	memmove (cmd, (char *)data, len);
161 	*(cmd + len) = 0;
162 
163 #ifdef CONFIG_SYS_HUSH_PARSER /*?? */
164 	rcode = parse_string_outer (cmd, FLAG_PARSE_SEMICOLON);
165 #else
166 	{
167 		char *line = cmd;
168 		char *next = cmd;
169 
170 		/*
171 		 * break into individual lines,
172 		 * and execute each line;
173 		 * terminate on error.
174 		 */
175 		while (*next) {
176 			if (*next == '\n') {
177 				*next = '\0';
178 				/* run only non-empty commands */
179 				if (*line) {
180 					debug ("** exec: \"%s\"\n",
181 						line);
182 					if (run_command (line, 0) < 0) {
183 						rcode = 1;
184 						break;
185 					}
186 				}
187 				line = next + 1;
188 			}
189 			++next;
190 		}
191 		if (rcode == 0 && *line)
192 			rcode = (run_command(line, 0) >= 0);
193 	}
194 #endif
195 	free (cmd);
196 	return rcode;
197 }
198 
199 /**************************************************/
200 #if defined(CONFIG_CMD_SOURCE)
201 int
do_source(cmd_tbl_t * cmdtp,int flag,int argc,char * argv[])202 do_source (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
203 {
204 	ulong addr;
205 	int rcode;
206 	const char *fit_uname = NULL;
207 
208 	/* Find script image */
209 	if (argc < 2) {
210 		addr = CONFIG_SYS_LOAD_ADDR;
211 		debug ("*  source: default load address = 0x%08lx\n", addr);
212 #if defined(CONFIG_FIT)
213 	} else if (fit_parse_subimage (argv[1], load_addr, &addr, &fit_uname)) {
214 		debug ("*  source: subimage '%s' from FIT image at 0x%08lx\n",
215 				fit_uname, addr);
216 #endif
217 	} else {
218 		addr = simple_strtoul(argv[1], NULL, 16);
219 		debug ("*  source: cmdline image address = 0x%08lx\n", addr);
220 	}
221 
222 	printf ("## Executing script at %08lx\n", addr);
223 	rcode = source (addr, fit_uname);
224 	return rcode;
225 }
226 
227 U_BOOT_CMD(
228 	source, 2, 0,	do_source,
229 	"run script from memory",
230 	"[addr]\n"
231 	"\t- run script starting at addr\n"
232 	"\t- A valid image header must be present"
233 #if defined(CONFIG_FIT)
234 	"\n"
235 	"For FIT format uImage addr must include subimage\n"
236 	"unit name in the form of addr:<subimg_uname>"
237 #endif
238 );
239 #endif
240