[new uImage] Fix autoscr command used with new uImage format
[kernel/u-boot.git] / common / cmd_autoscript.c
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  * autoscript allows a remote host to download a command file and,
26  * optionally, binary data for automatically updating the target. For
27  * example, you create a new kernel image and want the user to be
28  * able to simply download the image and the machine does the rest.
29  * The kernel image is postprocessed with mkimage, which creates an
30  * image with a script file prepended. If enabled, autoscript will
31  * verify the script and contents of the download and execute the
32  * script portion. This would be responsible for erasing flash,
33  * copying the new image, and rebooting the machine.
34  */
35
36 /* #define DEBUG */
37
38 #include <common.h>
39 #include <command.h>
40 #include <image.h>
41 #include <malloc.h>
42 #include <asm/byteorder.h>
43 #if defined(CONFIG_8xx)
44 #include <mpc8xx.h>
45 #endif
46 #ifdef CFG_HUSH_PARSER
47 #include <hush.h>
48 #endif
49
50 #if defined(CONFIG_AUTOSCRIPT) || defined(CONFIG_CMD_AUTOSCRIPT)
51
52 int
53 autoscript (ulong addr, const char *fit_uname)
54 {
55         ulong           len;
56         image_header_t  *hdr;
57         ulong           *data;
58         char            *cmd;
59         int             rcode = 0;
60         int             verify;
61 #if defined(CONFIG_FIT)
62         const void*     fit_hdr;
63         int             noffset;
64         const void      *fit_data;
65         size_t          fit_len;
66 #endif
67
68         verify = getenv_verify ();
69
70         switch (genimg_get_format ((void *)addr)) {
71         case IMAGE_FORMAT_LEGACY:
72                 hdr = (image_header_t *)addr;
73
74                 if (!image_check_magic (hdr)) {
75                         puts ("Bad magic number\n");
76                         return 1;
77                 }
78
79                 if (!image_check_hcrc (hdr)) {
80                         puts ("Bad header crc\n");
81                         return 1;
82                 }
83
84                 if (verify) {
85                         if (!image_check_dcrc (hdr)) {
86                                 puts ("Bad data crc\n");
87                                 return 1;
88                         }
89                 }
90
91                 if (!image_check_type (hdr, IH_TYPE_SCRIPT)) {
92                         puts ("Bad image type\n");
93                         return 1;
94                 }
95
96                 /* get length of script */
97                 data = (ulong *)image_get_data (hdr);
98
99                 if ((len = uimage_to_cpu (*data)) == 0) {
100                         puts ("Empty Script\n");
101                         return 1;
102                 }
103
104                 /*
105                  * scripts are just multi-image files with one component, seek
106                  * past the zero-terminated sequence of image lengths to get
107                  * to the actual image data
108                  */
109                 while (*data++);
110                 break;
111 #if defined(CONFIG_FIT)
112         case IMAGE_FORMAT_FIT:
113                 if (fit_uname == NULL) {
114                         puts ("No FIT subimage unit name\n");
115                         return 1;
116                 }
117
118                 fit_hdr = (const void *)addr;
119                 if (!fit_check_format (fit_hdr)) {
120                         puts ("Bad FIT image format\n");
121                         return 1;
122                 }
123
124                 /* get script component image node offset */
125                 noffset = fit_image_get_node (fit_hdr, fit_uname);
126                 if (noffset < 0) {
127                         printf ("Can't find '%s' FIT subimage\n", fit_uname);
128                         return 1;
129                 }
130
131                 if (!fit_image_check_type (fit_hdr, noffset, IH_TYPE_SCRIPT)) {
132                         puts ("Not a image image\n");
133                         return 1;
134                 }
135
136                 /* verify integrity */
137                 if (verify) {
138                         if (!fit_image_check_hashes (fit_hdr, noffset)) {
139                                 puts ("Bad Data Hash\n");
140                                 return 1;
141                         }
142                 }
143
144                 /* get script subimage data address and length */
145                 if (fit_image_get_data (fit_hdr, noffset, &fit_data, &fit_len)) {
146                         puts ("Could not find script subimage data\n");
147                         return 1;
148                 }
149
150                 data = (ulong *)fit_data;
151                 len = (ulong)fit_len;
152                 break;
153 #endif
154         default:
155                 puts ("Wrong image format for autoscript\n");
156                 return 1;
157         }
158
159         debug ("** Script length: %ld\n", len);
160
161         if ((cmd = malloc (len + 1)) == NULL) {
162                 return 1;
163         }
164
165         /* make sure cmd is null terminated */
166         memmove (cmd, (char *)data, len);
167         *(cmd + len) = 0;
168
169 #ifdef CFG_HUSH_PARSER /*?? */
170         rcode = parse_string_outer (cmd, FLAG_PARSE_SEMICOLON);
171 #else
172         {
173                 char *line = cmd;
174                 char *next = cmd;
175
176                 /*
177                  * break into individual lines,
178                  * and execute each line;
179                  * terminate on error.
180                  */
181                 while (*next) {
182                         if (*next == '\n') {
183                                 *next = '\0';
184                                 /* run only non-empty commands */
185                                 if ((next - line) > 1) {
186                                         debug ("** exec: \"%s\"\n",
187                                                 line);
188                                         if (run_command (line, 0) < 0) {
189                                                 rcode = 1;
190                                                 break;
191                                         }
192                                 }
193                                 line = next + 1;
194                         }
195                         ++next;
196                 }
197         }
198 #endif
199         free (cmd);
200         return rcode;
201 }
202
203 #endif
204
205 /**************************************************/
206 #if defined(CONFIG_CMD_AUTOSCRIPT)
207 int
208 do_autoscript (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
209 {
210         ulong addr;
211         int rcode;
212         const char *fit_uname = NULL;
213
214         /* Find script image */
215         if (argc < 2) {
216                 addr = CFG_LOAD_ADDR;
217                 debug ("*  autoscr: default load address = 0x%08lx\n", addr);
218 #if defined(CONFIG_FIT)
219         } else if (fit_parse_subimage (argv[1], load_addr, &addr, &fit_uname)) {
220                 debug ("*  autoscr: subimage '%s' from FIT image at 0x%08lx\n",
221                                 fit_uname, addr);
222 #endif
223         } else {
224                 addr = simple_strtoul(argv[1], NULL, 16);
225                 debug ("*  autoscr: cmdline image address = 0x%08lx\n", addr);
226         }
227
228         printf ("## Executing script at %08lx\n", addr);
229         rcode = autoscript (addr, fit_uname);
230         return rcode;
231 }
232
233 U_BOOT_CMD(
234         autoscr, 2, 0,  do_autoscript,
235         "autoscr - run script from memory\n",
236         "[addr] - run script starting at addr"
237         " - A valid autoscr header must be present\n"
238 #if defined(CONFIG_FIT)
239         "For FIT format uImage addr must include subimage\n"
240         "unit name in the form of addr:<subimg_uname>\n"
241 #endif
242 );
243 #endif