uboot/tools/dumpimage.c
<<
>>
Prefs
   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
  13static void usage(void);
  14
  15/* image_type_params linked list to maintain registered image types supports */
  16static struct image_type_params *dumpimage_tparams;
  17
  18/* parameters initialized by core will be used by the image type code */
  19static struct image_tool_params params = {
  20        .type = IH_TYPE_KERNEL,
  21};
  22
  23/**
  24 * dumpimage_register() - register respective image generation/list support
  25 *
  26 * the input struct image_type_params is checked and appended to the link
  27 * list, if the input structure is already registered, issue an error
  28 *
  29 * @tparams: Image type parameters
  30 */
  31static void dumpimage_register(struct image_type_params *tparams)
  32{
  33        struct image_type_params **tp;
  34
  35        if (!tparams) {
  36                fprintf(stderr, "%s: %s: Null input\n", params.cmdname,
  37                        __func__);
  38                exit(EXIT_FAILURE);
  39        }
  40
  41        /* scan the linked list, check for registry and point the last one */
  42        for (tp = &dumpimage_tparams; *tp != NULL; tp = &(*tp)->next) {
  43                if (!strcmp((*tp)->name, tparams->name)) {
  44                        fprintf(stderr, "%s: %s already registered\n",
  45                                params.cmdname, tparams->name);
  46                        return;
  47                }
  48        }
  49
  50        /* add input struct entry at the end of link list */
  51        *tp = tparams;
  52        /* mark input entry as last entry in the link list */
  53        tparams->next = NULL;
  54
  55        debug("Registered %s\n", tparams->name);
  56}
  57
  58/**
  59 * dumpimage_get_type() - find the image type params for a given image type
  60 *
  61 * Scan all registered image types and check the input type_id for each
  62 * supported image type
  63 *
  64 * @return respective image_type_params pointer. If the input type is not
  65 * supported by any of registered image types, returns NULL
  66 */
  67static struct image_type_params *dumpimage_get_type(int type)
  68{
  69        struct image_type_params *curr;
  70
  71        for (curr = dumpimage_tparams; curr != NULL; curr = curr->next) {
  72                if (curr->check_image_type) {
  73                        if (!curr->check_image_type(type))
  74                                return curr;
  75                }
  76        }
  77        return NULL;
  78}
  79
  80/*
  81 * dumpimage_verify_print_header() - verifies the image header
  82 *
  83 * Scan registered image types and verify the image_header for each
  84 * supported image type. If verification is successful, this prints
  85 * the respective header.
  86 *
  87 * @return 0 on success, negative if input image format does not match with
  88 * any of supported image types
  89 */
  90static int dumpimage_verify_print_header(void *ptr, struct stat *sbuf)
  91{
  92        int retval = -1;
  93        struct image_type_params *curr;
  94
  95        for (curr = dumpimage_tparams; curr != NULL; curr = curr->next) {
  96                if (curr->verify_header) {
  97                        retval = curr->verify_header((unsigned char *)ptr,
  98                                                     sbuf->st_size, &params);
  99                        if (retval != 0)
 100                                continue;
 101                        /*
 102                         * Print the image information  if verify is
 103                         * successful
 104                         */
 105                        if (curr->print_header) {
 106                                curr->print_header(ptr);
 107                        } else {
 108                                fprintf(stderr,
 109                                        "%s: print_header undefined for %s\n",
 110                                        params.cmdname, curr->name);
 111                        }
 112                        break;
 113                }
 114        }
 115
 116        return retval;
 117}
 118
 119/*
 120 * dumpimage_extract_datafile -
 121 *
 122 * It scans all registered image types,
 123 * verifies image_header for each supported image type
 124 * if verification is successful, it extracts the desired file,
 125 * indexed by pflag, from the image
 126 *
 127 * returns negative if input image format does not match with any of
 128 * supported image types
 129 */
 130static int dumpimage_extract_datafile(void *ptr, struct stat *sbuf)
 131{
 132        int retval = -1;
 133        struct image_type_params *curr;
 134
 135        for (curr = dumpimage_tparams; curr != NULL; curr = curr->next) {
 136                if (curr->verify_header) {
 137                        retval = curr->verify_header((unsigned char *)ptr,
 138                                                     sbuf->st_size, &params);
 139                        if (retval != 0)
 140                                continue;
 141                        /*
 142                         * Extract the file from the image
 143                         * if verify is successful
 144                         */
 145                        if (curr->extract_datafile) {
 146                                curr->extract_datafile(ptr, &params);
 147                        } else {
 148                                fprintf(stderr,
 149                                        "%s: extract_datafile undefined for %s\n",
 150                                        params.cmdname, curr->name);
 151                        break;
 152                        }
 153                }
 154        }
 155
 156        return retval;
 157}
 158
 159int main(int argc, char **argv)
 160{
 161        int opt;
 162        int ifd = -1;
 163        struct stat sbuf;
 164        char *ptr;
 165        int retval = 0;
 166        struct image_type_params *tparams = NULL;
 167
 168        /* Init all image generation/list support */
 169        register_image_tool(dumpimage_register);
 170
 171        params.cmdname = *argv;
 172
 173        while ((opt = getopt(argc, argv, "li:o:p:V")) != -1) {
 174                switch (opt) {
 175                case 'l':
 176                        params.lflag = 1;
 177                        break;
 178                case 'i':
 179                        params.imagefile = optarg;
 180                        params.iflag = 1;
 181                        break;
 182                case 'o':
 183                        params.outfile = optarg;
 184                        break;
 185                case 'p':
 186                        params.pflag = strtoul(optarg, &ptr, 10);
 187                        if (*ptr) {
 188                                fprintf(stderr,
 189                                        "%s: invalid file position %s\n",
 190                                        params.cmdname, *argv);
 191                                exit(EXIT_FAILURE);
 192                        }
 193                        break;
 194                case 'V':
 195                        printf("dumpimage version %s\n", PLAIN_VERSION);
 196                        exit(EXIT_SUCCESS);
 197                default:
 198                        usage();
 199                }
 200        }
 201
 202        if (optind >= argc)
 203                usage();
 204
 205        /* set tparams as per input type_id */
 206        tparams = dumpimage_get_type(params.type);
 207        if (tparams == NULL) {
 208                fprintf(stderr, "%s: unsupported type %s\n",
 209                        params.cmdname, genimg_get_type_name(params.type));
 210                exit(EXIT_FAILURE);
 211        }
 212
 213        /*
 214         * check the passed arguments parameters meets the requirements
 215         * as per image type to be generated/listed
 216         */
 217        if (tparams->check_params) {
 218                if (tparams->check_params(&params))
 219                        usage();
 220        }
 221
 222        if (params.iflag)
 223                params.datafile = argv[optind];
 224        else
 225                params.imagefile = argv[optind];
 226        if (!params.outfile)
 227                params.outfile = params.datafile;
 228
 229        ifd = open(params.imagefile, O_RDONLY|O_BINARY);
 230        if (ifd < 0) {
 231                fprintf(stderr, "%s: Can't open \"%s\": %s\n",
 232                        params.cmdname, params.imagefile,
 233                        strerror(errno));
 234                exit(EXIT_FAILURE);
 235        }
 236
 237        if (params.lflag || params.iflag) {
 238                if (fstat(ifd, &sbuf) < 0) {
 239                        fprintf(stderr, "%s: Can't stat \"%s\": %s\n",
 240                                params.cmdname, params.imagefile,
 241                                strerror(errno));
 242                        exit(EXIT_FAILURE);
 243                }
 244
 245                if ((unsigned)sbuf.st_size < tparams->header_size) {
 246                        fprintf(stderr,
 247                                "%s: Bad size: \"%s\" is not valid image\n",
 248                                params.cmdname, params.imagefile);
 249                        exit(EXIT_FAILURE);
 250                }
 251
 252                ptr = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, ifd, 0);
 253                if (ptr == MAP_FAILED) {
 254                        fprintf(stderr, "%s: Can't read \"%s\": %s\n",
 255                                params.cmdname, params.imagefile,
 256                                strerror(errno));
 257                        exit(EXIT_FAILURE);
 258                }
 259
 260                /*
 261                 * Both calls bellow scan through dumpimage registry for all
 262                 * supported image types and verify the input image file
 263                 * header for match
 264                 */
 265                if (params.iflag) {
 266                        /*
 267                         * Extract the data files from within the matched
 268                         * image type. Returns the error code if not matched
 269                         */
 270                        retval = dumpimage_extract_datafile(ptr, &sbuf);
 271                } else {
 272                        /*
 273                         * Print the image information for matched image type
 274                         * Returns the error code if not matched
 275                         */
 276                        retval = dumpimage_verify_print_header(ptr, &sbuf);
 277                }
 278
 279                (void)munmap((void *)ptr, sbuf.st_size);
 280                (void)close(ifd);
 281
 282                return retval;
 283        }
 284
 285        (void)close(ifd);
 286
 287        return EXIT_SUCCESS;
 288}
 289
 290static void usage(void)
 291{
 292        fprintf(stderr, "Usage: %s -l image\n"
 293                "          -l ==> list image header information\n",
 294                params.cmdname);
 295        fprintf(stderr,
 296                "       %s -i image [-p position] [-o outfile] data_file\n"
 297                "          -i ==> extract from the 'image' a specific 'data_file'"
 298                ", indexed by 'position' (starting at 0)\n",
 299                params.cmdname);
 300        fprintf(stderr,
 301                "       %s -V ==> print version information and exit\n",
 302                params.cmdname);
 303
 304        exit(EXIT_FAILURE);
 305}
 306