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