xref: /rk3399_rockchip-uboot/tools/dumpimage.c (revision a93648d197df48fa46dd55f925ff70468bd81c71)
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, &params);
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, &params);
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(&params))
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, &params);
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