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, ALIGN(len, ARCH_DMA_MINALIGN)); 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