cmd_ximg.c 5.82 KB
Newer Older
1 2 3 4 5 6 7
/*
 * (C) Copyright 2000-2004
 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
 *
 * (C) Copyright 2003
 * Kai-Uwe Bloem, Auerswald GmbH & Co KG, <linux-development@auerswald.de>
 *
8
 * SPDX-License-Identifier:	GPL-2.0+
9 10 11 12 13 14 15 16 17
 */


/*
 * Multi Image extract
 */
#include <common.h>
#include <command.h>
#include <image.h>
18
#include <mapmem.h>
19 20 21 22
#include <watchdog.h>
#if defined(CONFIG_BZIP2)
#include <bzlib.h>
#endif
23
#include <asm/byteorder.h>
24
#include <asm/io.h>
25

26 27 28 29 30
#ifndef CONFIG_SYS_XIMG_LEN
/* use 8MByte as default max gunzip size */
#define CONFIG_SYS_XIMG_LEN	0x800000
#endif

31
static int
32
do_imgextract(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
33
{
34 35
	ulong		addr = load_addr;
	ulong		dest = 0;
36
	ulong		data, len;
37
	int		verify;
38
	int		part = 0;
39 40
#if defined(CONFIG_IMAGE_FORMAT_LEGACY)
	ulong		count;
41
	image_header_t	*hdr = NULL;
42
#endif
43
#if defined(CONFIG_FIT)
44
	const char	*uname = NULL;
45 46 47 48 49
	const void*	fit_hdr;
	int		noffset;
	const void	*fit_data;
	size_t		fit_len;
#endif
50
#ifdef CONFIG_GZIP
51
	uint		unc_len = CONFIG_SYS_XIMG_LEN;
52
#endif
53
	uint8_t		comp;
54

55
	verify = getenv_yesno("verify");
56 57 58 59 60 61

	if (argc > 1) {
		addr = simple_strtoul(argv[1], NULL, 16);
	}
	if (argc > 2) {
		part = simple_strtoul(argv[2], NULL, 16);
62 63 64
#if defined(CONFIG_FIT)
		uname = argv[2];
#endif
65 66 67 68 69
	}
	if (argc > 3) {
		dest = simple_strtoul(argv[3], NULL, 16);
	}

70
	switch (genimg_get_format((void *)addr)) {
71
#if defined(CONFIG_IMAGE_FORMAT_LEGACY)
72
	case IMAGE_FORMAT_LEGACY:
73

74 75 76
		printf("## Copying part %d from legacy image "
			"at %08lx ...\n", part, addr);

77
		hdr = (image_header_t *)addr;
78
		if (!image_check_magic(hdr)) {
79 80 81
			printf("Bad Magic Number\n");
			return 1;
		}
82

83
		if (!image_check_hcrc(hdr)) {
84 85 86
			printf("Bad Header Checksum\n");
			return 1;
		}
87
#ifdef DEBUG
88
		image_print_contents(hdr);
89
#endif
90

91 92
		if (!image_check_type(hdr, IH_TYPE_MULTI) &&
		    !image_check_type(hdr, IH_TYPE_SCRIPT)) {
93 94 95 96
			printf("Wrong Image Type for %s command\n",
					cmdtp->name);
			return 1;
		}
97

98
		comp = image_get_comp(hdr);
99 100 101
		if ((comp != IH_COMP_NONE) && (argc < 4)) {
			printf("Must specify load address for %s command "
					"with compressed image\n",
102
					cmdtp->name);
103 104 105
			return 1;
		}

106 107
		if (verify) {
			printf("   Verifying Checksum ... ");
108
			if (!image_check_dcrc(hdr)) {
109 110
				printf("Bad Data CRC\n");
				return 1;
111
			}
112
			printf("OK\n");
113
		}
114

115
		count = image_multi_count(hdr);
116
		if (part >= count) {
117 118 119
			printf("Bad Image Part\n");
			return 1;
		}
120

121
		image_multi_getimg(hdr, part, &data, &len);
122
		break;
123
#endif
124 125
#if defined(CONFIG_FIT)
	case IMAGE_FORMAT_FIT:
126
		if (uname == NULL) {
127
			puts("No FIT subimage unit name\n");
128 129 130 131 132 133 134
			return 1;
		}

		printf("## Copying '%s' subimage from FIT image "
			"at %08lx ...\n", uname, addr);

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

		/* 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 145 146
			return 1;
		}

147
		if (fit_image_check_comp(fit_hdr, noffset, IH_COMP_NONE)
148 149 150 151
		    && (argc < 4)) {
			printf("Must specify load address for %s command "
				"with compressed image\n",
				cmdtp->name);
152 153 154 155 156
			return 1;
		}

		/* verify integrity */
		if (verify) {
157
			if (!fit_image_verify(fit_hdr, noffset)) {
158
				puts("Bad Data Hash\n");
159 160 161 162 163
				return 1;
			}
		}

		/* 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 168 169
			return 1;
		}

170 171
		if (fit_image_get_comp(fit_hdr, noffset, &comp)) {
			puts("Could not find script subimage "
172 173 174 175
				"compression type\n");
			return 1;
		}

176
		data = (ulong)fit_data;
177 178
		len = (ulong)fit_len;
		break;
179 180
#endif
	default:
181
		puts("Invalid image type for imxtract\n");
182 183 184 185
		return 1;
	}

	if (argc > 3) {
186 187 188 189 190 191 192 193 194
		switch (comp) {
		case IH_COMP_NONE:
#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
			{
				size_t l = len;
				size_t tail;
				void *to = (void *) dest;
				void *from = (void *)data;

195
				printf("   Loading part %d ... ", part);
196 197 198 199

				while (l > 0) {
					tail = (l > CHUNKSZ) ? CHUNKSZ : l;
					WATCHDOG_RESET();
200
					memmove(to, from, tail);
201 202 203 204 205 206
					to += tail;
					from += tail;
					l -= tail;
				}
			}
#else	/* !(CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG) */
207 208
			printf("   Loading part %d ... ", part);
			memmove((char *) dest, (char *)data, len);
209 210
#endif	/* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */
			break;
211
#ifdef CONFIG_GZIP
212
		case IH_COMP_GZIP:
213 214 215 216
			printf("   Uncompressing part %d ... ", part);
			if (gunzip((void *) dest, unc_len,
				   (uchar *) data, &len) != 0) {
				puts("GUNZIP ERROR - image not loaded\n");
217 218 219
				return 1;
			}
			break;
220
#endif
221
#if defined(CONFIG_BZIP2) && defined(CONFIG_IMAGE_FORMAT_LEGACY)
222
		case IH_COMP_BZIP2:
223 224 225
			{
				int i;

226
				printf("   Uncompressing part %d ... ", part);
227
				/*
Wolfgang Denk's avatar
Wolfgang Denk committed
228
				 * If we've got less than 4 MB of malloc()
229 230 231 232
				 * space, use slower decompression algorithm
				 * which requires at most 2300 KB of memory.
				 */
				i = BZ2_bzBuffToBuffDecompress(
233
					map_sysmem(ntohl(hdr->ih_load), 0),
234 235 236 237
					&unc_len, (char *)data, len,
					CONFIG_SYS_MALLOC_LEN < (4096 * 1024),
					0);
				if (i != BZ_OK) {
238
					printf("BUNZIP2 ERROR %d - "
239 240 241
						"image not loaded\n", i);
					return 1;
				}
242 243 244 245
			}
			break;
#endif /* CONFIG_BZIP2 */
		default:
246
			printf("Unimplemented compression type %d\n", comp);
247 248
			return 1;
		}
249
		puts("OK\n");
250 251
	}

252 253
	flush_cache(dest, len);

254 255
	setenv_hex("fileaddr", data);
	setenv_hex("filesize", len);
256 257 258 259

	return 0;
}

260 261
#ifdef CONFIG_SYS_LONGHELP
static char imgextract_help_text[] =
262 263
	"addr part [dest]\n"
	"    - extract <part> from legacy image at <addr> and copy to <dest>"
264
#if defined(CONFIG_FIT)
265 266 267
	"\n"
	"addr uname [dest]\n"
	"    - extract <uname> subimage from FIT image at <addr> and copy to <dest>"
268
#endif
269 270 271 272 273 274
	"";
#endif

U_BOOT_CMD(
	imxtract, 4, 1, do_imgextract,
	"extract a part of a multi-image", imgextract_help_text
275
);