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