xref: /openbmc/u-boot/cmd/ximg.c (revision 723806cc5bea9f8b37323dfd7568603f99af6a06)
1  /*
2   * (C) Copyright 2000-2004
3   * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4   *
5   * (C) Copyright 2003
6   * Kai-Uwe Bloem, Auerswald GmbH & Co KG, <linux-development@auerswald.de>
7   *
8   * SPDX-License-Identifier:	GPL-2.0+
9   */
10  
11  
12  /*
13   * Multi Image extract
14   */
15  #include <common.h>
16  #include <command.h>
17  #include <image.h>
18  #include <mapmem.h>
19  #include <watchdog.h>
20  #if defined(CONFIG_BZIP2)
21  #include <bzlib.h>
22  #endif
23  #include <asm/byteorder.h>
24  #include <asm/io.h>
25  
26  #ifndef CONFIG_SYS_XIMG_LEN
27  /* use 8MByte as default max gunzip size */
28  #define CONFIG_SYS_XIMG_LEN	0x800000
29  #endif
30  
31  static int
32  do_imgextract(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
33  {
34  	ulong		addr = load_addr;
35  	ulong		dest = 0;
36  	ulong		data, len;
37  	int		verify;
38  	int		part = 0;
39  #if defined(CONFIG_IMAGE_FORMAT_LEGACY)
40  	ulong		count;
41  	image_header_t	*hdr = NULL;
42  #endif
43  #if defined(CONFIG_FIT)
44  	const char	*uname = NULL;
45  	const void*	fit_hdr;
46  	int		noffset;
47  	const void	*fit_data;
48  	size_t		fit_len;
49  #endif
50  #ifdef CONFIG_GZIP
51  	uint		unc_len = CONFIG_SYS_XIMG_LEN;
52  #endif
53  	uint8_t		comp;
54  
55  	verify = env_get_yesno("verify");
56  
57  	if (argc > 1) {
58  		addr = simple_strtoul(argv[1], NULL, 16);
59  	}
60  	if (argc > 2) {
61  		part = simple_strtoul(argv[2], NULL, 16);
62  #if defined(CONFIG_FIT)
63  		uname = argv[2];
64  #endif
65  	}
66  	if (argc > 3) {
67  		dest = simple_strtoul(argv[3], NULL, 16);
68  	}
69  
70  	switch (genimg_get_format((void *)addr)) {
71  #if defined(CONFIG_IMAGE_FORMAT_LEGACY)
72  	case IMAGE_FORMAT_LEGACY:
73  
74  		printf("## Copying part %d from legacy image "
75  			"at %08lx ...\n", part, addr);
76  
77  		hdr = (image_header_t *)addr;
78  		if (!image_check_magic(hdr)) {
79  			printf("Bad Magic Number\n");
80  			return 1;
81  		}
82  
83  		if (!image_check_hcrc(hdr)) {
84  			printf("Bad Header Checksum\n");
85  			return 1;
86  		}
87  #ifdef DEBUG
88  		image_print_contents(hdr);
89  #endif
90  
91  		if (!image_check_type(hdr, IH_TYPE_MULTI) &&
92  		    !image_check_type(hdr, IH_TYPE_SCRIPT)) {
93  			printf("Wrong Image Type for %s command\n",
94  					cmdtp->name);
95  			return 1;
96  		}
97  
98  		comp = image_get_comp(hdr);
99  		if ((comp != IH_COMP_NONE) && (argc < 4)) {
100  			printf("Must specify load address for %s command "
101  					"with compressed image\n",
102  					cmdtp->name);
103  			return 1;
104  		}
105  
106  		if (verify) {
107  			printf("   Verifying Checksum ... ");
108  			if (!image_check_dcrc(hdr)) {
109  				printf("Bad Data CRC\n");
110  				return 1;
111  			}
112  			printf("OK\n");
113  		}
114  
115  		count = image_multi_count(hdr);
116  		if (part >= count) {
117  			printf("Bad Image Part\n");
118  			return 1;
119  		}
120  
121  		image_multi_getimg(hdr, part, &data, &len);
122  		break;
123  #endif
124  #if defined(CONFIG_FIT)
125  	case IMAGE_FORMAT_FIT:
126  		if (uname == NULL) {
127  			puts("No FIT subimage unit name\n");
128  			return 1;
129  		}
130  
131  		printf("## Copying '%s' subimage from FIT image "
132  			"at %08lx ...\n", uname, addr);
133  
134  		fit_hdr = (const void *)addr;
135  		if (!fit_check_format(fit_hdr)) {
136  			puts("Bad FIT image format\n");
137  			return 1;
138  		}
139  
140  		/* get subimage node offset */
141  		noffset = fit_image_get_node(fit_hdr, uname);
142  		if (noffset < 0) {
143  			printf("Can't find '%s' FIT subimage\n", uname);
144  			return 1;
145  		}
146  
147  		if (fit_image_check_comp(fit_hdr, noffset, IH_COMP_NONE)
148  		    && (argc < 4)) {
149  			printf("Must specify load address for %s command "
150  				"with compressed image\n",
151  				cmdtp->name);
152  			return 1;
153  		}
154  
155  		/* verify integrity */
156  		if (verify) {
157  			if (!fit_image_verify(fit_hdr, noffset)) {
158  				puts("Bad Data Hash\n");
159  				return 1;
160  			}
161  		}
162  
163  		/* get subimage data address and length */
164  		if (fit_image_get_data(fit_hdr, noffset,
165  					&fit_data, &fit_len)) {
166  			puts("Could not find script subimage data\n");
167  			return 1;
168  		}
169  
170  		if (fit_image_get_comp(fit_hdr, noffset, &comp)) {
171  			puts("Could not find script subimage "
172  				"compression type\n");
173  			return 1;
174  		}
175  
176  		data = (ulong)fit_data;
177  		len = (ulong)fit_len;
178  		break;
179  #endif
180  	default:
181  		puts("Invalid image type for imxtract\n");
182  		return 1;
183  	}
184  
185  	if (argc > 3) {
186  		switch (comp) {
187  		case IH_COMP_NONE:
188  #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
189  			{
190  				size_t l = len;
191  				size_t tail;
192  				void *to = (void *) dest;
193  				void *from = (void *)data;
194  
195  				printf("   Loading part %d ... ", part);
196  
197  				while (l > 0) {
198  					tail = (l > CHUNKSZ) ? CHUNKSZ : l;
199  					WATCHDOG_RESET();
200  					memmove(to, from, tail);
201  					to += tail;
202  					from += tail;
203  					l -= tail;
204  				}
205  			}
206  #else	/* !(CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG) */
207  			printf("   Loading part %d ... ", part);
208  			memmove((char *) dest, (char *)data, len);
209  #endif	/* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */
210  			break;
211  #ifdef CONFIG_GZIP
212  		case IH_COMP_GZIP:
213  			printf("   Uncompressing part %d ... ", part);
214  			if (gunzip((void *) dest, unc_len,
215  				   (uchar *) data, &len) != 0) {
216  				puts("GUNZIP ERROR - image not loaded\n");
217  				return 1;
218  			}
219  			break;
220  #endif
221  #if defined(CONFIG_BZIP2) && defined(CONFIG_IMAGE_FORMAT_LEGACY)
222  		case IH_COMP_BZIP2:
223  			{
224  				int i;
225  
226  				printf("   Uncompressing part %d ... ", part);
227  				/*
228  				 * If we've got less than 4 MB of malloc()
229  				 * space, use slower decompression algorithm
230  				 * which requires at most 2300 KB of memory.
231  				 */
232  				i = BZ2_bzBuffToBuffDecompress(
233  					map_sysmem(ntohl(hdr->ih_load), 0),
234  					&unc_len, (char *)data, len,
235  					CONFIG_SYS_MALLOC_LEN < (4096 * 1024),
236  					0);
237  				if (i != BZ_OK) {
238  					printf("BUNZIP2 ERROR %d - "
239  						"image not loaded\n", i);
240  					return 1;
241  				}
242  			}
243  			break;
244  #endif /* CONFIG_BZIP2 */
245  		default:
246  			printf("Unimplemented compression type %d\n", comp);
247  			return 1;
248  		}
249  		puts("OK\n");
250  	}
251  
252  	flush_cache(dest, len);
253  
254  	env_set_hex("fileaddr", data);
255  	env_set_hex("filesize", len);
256  
257  	return 0;
258  }
259  
260  #ifdef CONFIG_SYS_LONGHELP
261  static char imgextract_help_text[] =
262  	"addr part [dest]\n"
263  	"    - extract <part> from legacy image at <addr> and copy to <dest>"
264  #if defined(CONFIG_FIT)
265  	"\n"
266  	"addr uname [dest]\n"
267  	"    - extract <uname> subimage from FIT image at <addr> and copy to <dest>"
268  #endif
269  	"";
270  #endif
271  
272  U_BOOT_CMD(
273  	imxtract, 4, 1, do_imgextract,
274  	"extract a part of a multi-image", imgextract_help_text
275  );
276