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