xref: /openbmc/u-boot/cmd/ximg.c (revision ceff355a)
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