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, ¶ms);
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, ¶ms);
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(¶ms))
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, ¶ms);
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