1 /* 2 * Based on mkimage.c. 3 * 4 * Written by Guilherme Maciel Ferreira <guilherme.maciel.ferreira@gmail.com> 5 * 6 * SPDX-License-Identifier: GPL-2.0+ 7 */ 8 9 #include "dumpimage.h" 10 #include <image.h> 11 #include <version.h> 12 13 static void usage(void); 14 15 /* image_type_params linked list to maintain registered image types supports */ 16 static struct image_type_params *dumpimage_tparams; 17 18 /* parameters initialized by core will be used by the image type code */ 19 static struct image_tool_params params = { 20 .type = IH_TYPE_KERNEL, 21 }; 22 23 /* 24 * dumpimage_extract_datafile - 25 * 26 * It scans all registered image types, 27 * verifies image_header for each supported image type 28 * if verification is successful, it extracts the desired file, 29 * indexed by pflag, from the image 30 * 31 * returns negative if input image format does not match with any of 32 * supported image types 33 */ 34 static int dumpimage_extract_datafile(void *ptr, struct stat *sbuf) 35 { 36 int retval = -1; 37 struct image_type_params *curr; 38 struct image_type_params *start = ll_entry_start( 39 struct image_type_params, image_type); 40 struct image_type_params *end = ll_entry_end( 41 struct image_type_params, image_type); 42 43 for (curr = start; curr != end; curr++) { 44 if (curr->verify_header) { 45 retval = curr->verify_header((unsigned char *)ptr, 46 sbuf->st_size, ¶ms); 47 if (retval != 0) 48 continue; 49 /* 50 * Extract the file from the image 51 * if verify is successful 52 */ 53 if (curr->extract_datafile) { 54 curr->extract_datafile(ptr, ¶ms); 55 } else { 56 fprintf(stderr, 57 "%s: extract_datafile undefined for %s\n", 58 params.cmdname, curr->name); 59 break; 60 } 61 } 62 } 63 64 return retval; 65 } 66 67 int main(int argc, char **argv) 68 { 69 int opt; 70 int ifd = -1; 71 struct stat sbuf; 72 char *ptr; 73 int retval = 0; 74 struct image_type_params *tparams = NULL; 75 76 params.cmdname = *argv; 77 78 while ((opt = getopt(argc, argv, "li:o:p:V")) != -1) { 79 switch (opt) { 80 case 'l': 81 params.lflag = 1; 82 break; 83 case 'i': 84 params.imagefile = optarg; 85 params.iflag = 1; 86 break; 87 case 'o': 88 params.outfile = optarg; 89 break; 90 case 'p': 91 params.pflag = strtoul(optarg, &ptr, 10); 92 if (*ptr) { 93 fprintf(stderr, 94 "%s: invalid file position %s\n", 95 params.cmdname, *argv); 96 exit(EXIT_FAILURE); 97 } 98 break; 99 case 'V': 100 printf("dumpimage version %s\n", PLAIN_VERSION); 101 exit(EXIT_SUCCESS); 102 default: 103 usage(); 104 } 105 } 106 107 if (optind >= argc) 108 usage(); 109 110 /* set tparams as per input type_id */ 111 tparams = imagetool_get_type(params.type); 112 if (tparams == NULL) { 113 fprintf(stderr, "%s: unsupported type %s\n", 114 params.cmdname, genimg_get_type_name(params.type)); 115 exit(EXIT_FAILURE); 116 } 117 118 /* 119 * check the passed arguments parameters meets the requirements 120 * as per image type to be generated/listed 121 */ 122 if (tparams->check_params) { 123 if (tparams->check_params(¶ms)) 124 usage(); 125 } 126 127 if (params.iflag) 128 params.datafile = argv[optind]; 129 else 130 params.imagefile = argv[optind]; 131 if (!params.outfile) 132 params.outfile = params.datafile; 133 134 ifd = open(params.imagefile, O_RDONLY|O_BINARY); 135 if (ifd < 0) { 136 fprintf(stderr, "%s: Can't open \"%s\": %s\n", 137 params.cmdname, params.imagefile, 138 strerror(errno)); 139 exit(EXIT_FAILURE); 140 } 141 142 if (params.lflag || params.iflag) { 143 if (fstat(ifd, &sbuf) < 0) { 144 fprintf(stderr, "%s: Can't stat \"%s\": %s\n", 145 params.cmdname, params.imagefile, 146 strerror(errno)); 147 exit(EXIT_FAILURE); 148 } 149 150 if ((unsigned)sbuf.st_size < tparams->header_size) { 151 fprintf(stderr, 152 "%s: Bad size: \"%s\" is not valid image\n", 153 params.cmdname, params.imagefile); 154 exit(EXIT_FAILURE); 155 } 156 157 ptr = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, ifd, 0); 158 if (ptr == MAP_FAILED) { 159 fprintf(stderr, "%s: Can't read \"%s\": %s\n", 160 params.cmdname, params.imagefile, 161 strerror(errno)); 162 exit(EXIT_FAILURE); 163 } 164 165 /* 166 * Both calls bellow scan through dumpimage registry for all 167 * supported image types and verify the input image file 168 * header for match 169 */ 170 if (params.iflag) { 171 /* 172 * Extract the data files from within the matched 173 * image type. Returns the error code if not matched 174 */ 175 retval = dumpimage_extract_datafile(ptr, &sbuf); 176 } else { 177 /* 178 * Print the image information for matched image type 179 * Returns the error code if not matched 180 */ 181 retval = imagetool_verify_print_header(ptr, &sbuf, 182 tparams, ¶ms); 183 } 184 185 (void)munmap((void *)ptr, sbuf.st_size); 186 (void)close(ifd); 187 188 return retval; 189 } 190 191 (void)close(ifd); 192 193 return EXIT_SUCCESS; 194 } 195 196 static void usage(void) 197 { 198 fprintf(stderr, "Usage: %s -l image\n" 199 " -l ==> list image header information\n", 200 params.cmdname); 201 fprintf(stderr, 202 " %s -i image [-p position] [-o outfile] data_file\n" 203 " -i ==> extract from the 'image' a specific 'data_file'" 204 ", indexed by 'position' (starting at 0)\n", 205 params.cmdname); 206 fprintf(stderr, 207 " %s -V ==> print version information and exit\n", 208 params.cmdname); 209 210 exit(EXIT_FAILURE); 211 } 212