diff --git a/tools/Makefile b/tools/Makefile index 6f36f23dc..858b0e8f0 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -183,8 +183,15 @@ $(obj)inca-swap-bytes$(SFX): $(obj)inca-swap-bytes.o $(CC) $(CFLAGS) $(HOST_LDFLAGS) -o $@ $^ $(STRIP) $@ -$(obj)mkimage$(SFX): $(obj)crc32.o $(obj)mkimage.o $(obj)image.o $(obj)md5.o $(obj)mkimage.o \ - $(obj)os_support.o $(obj)sha1.o $(LIBFDT_OBJS) +$(obj)mkimage$(SFX): $(obj)crc32.o \ + $(obj)default_image.o \ + $(obj)fit_image.o \ + $(obj)image.o \ + $(obj)md5.o \ + $(obj)mkimage.o \ + $(obj)os_support.o \ + $(obj)sha1.o \ + $(LIBFDT_OBJS) $(CC) $(CFLAGS) $(HOST_LDFLAGS) -o $@ $^ $(STRIP) $@ @@ -200,6 +207,12 @@ $(obj)ubsha1$(SFX): $(obj)os_support.o $(obj)sha1.o $(obj)ubsha1.o $(CC) $(CFLAGS) -o $@ $^ # Some files complain if compiled with -pedantic, use FIT_CFLAGS +$(obj)default_image.o: $(SRCTREE)/tools/default_image.c + $(CC) -g $(FIT_CFLAGS) -c -o $@ $< + +$(obj)fit_image.o: $(SRCTREE)/tools/fit_image.c + $(CC) -g $(FIT_CFLAGS) -c -o $@ $< + $(obj)image.o: $(SRCTREE)/common/image.c $(CC) -g $(FIT_CFLAGS) -c -o $@ $< diff --git a/tools/default_image.c b/tools/default_image.c new file mode 100644 index 000000000..f5bad4757 --- /dev/null +++ b/tools/default_image.c @@ -0,0 +1,149 @@ +/* + * (C) Copyright 2008 Semihalf + * + * (C) Copyright 2000-2004 + * DENX Software Engineering + * Wolfgang Denk, wd@denx.de + * + * Updated-by: Prafulla Wadaskar + * default_image specific code abstracted from mkimage.c + * some functions added to address abstraction + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include "mkimage.h" +#include +#include + +static image_header_t header; + +static int image_check_image_types (uint8_t type) +{ + if ((type > IH_TYPE_INVALID) && (type < IH_TYPE_FLATDT)) + return EXIT_SUCCESS; + else + return EXIT_FAILURE; +} + +static int image_check_params (struct mkimage_params *params) +{ + return ((params->dflag && (params->fflag || params->lflag)) || + (params->fflag && (params->dflag || params->lflag)) || + (params->lflag && (params->dflag || params->fflag))); +} + +static int image_verify_header (unsigned char *ptr, int image_size, + struct mkimage_params *params) +{ + uint32_t len; + const unsigned char *data; + uint32_t checksum; + image_header_t header; + image_header_t *hdr = &header; + + /* + * create copy of header so that we can blank out the + * checksum field for checking - this can't be done + * on the PROT_READ mapped data. + */ + memcpy (hdr, ptr, sizeof(image_header_t)); + + if (be32_to_cpu(hdr->ih_magic) != IH_MAGIC) { + fprintf (stderr, + "%s: Bad Magic Number: \"%s\" is no valid image\n", + params->cmdname, params->imagefile); + return -FDT_ERR_BADMAGIC; + } + + data = (const unsigned char *)hdr; + len = sizeof(image_header_t); + + checksum = be32_to_cpu(hdr->ih_hcrc); + hdr->ih_hcrc = cpu_to_be32(0); /* clear for re-calculation */ + + if (crc32 (0, data, len) != checksum) { + fprintf (stderr, + "%s: ERROR: \"%s\" has bad header checksum!\n", + params->cmdname, params->imagefile); + return -FDT_ERR_BADSTATE; + } + + data = (const unsigned char *)ptr + sizeof(image_header_t); + len = image_size - sizeof(image_header_t) ; + + checksum = be32_to_cpu(hdr->ih_dcrc); + if (crc32 (0, data, len) != checksum) { + fprintf (stderr, + "%s: ERROR: \"%s\" has corrupted data!\n", + params->cmdname, params->imagefile); + return -FDT_ERR_BADSTRUCTURE; + } + return 0; +} + +static void image_set_header (void *ptr, struct stat *sbuf, int ifd, + struct mkimage_params *params) +{ + uint32_t checksum; + + image_header_t * hdr = (image_header_t *)ptr; + + checksum = crc32 (0, + (const unsigned char *)(ptr + + sizeof(image_header_t)), + sbuf->st_size - sizeof(image_header_t)); + + /* Build new header */ + image_set_magic (hdr, IH_MAGIC); + image_set_time (hdr, sbuf->st_mtime); + image_set_size (hdr, sbuf->st_size - sizeof(image_header_t)); + image_set_load (hdr, params->addr); + image_set_ep (hdr, params->ep); + image_set_dcrc (hdr, checksum); + image_set_os (hdr, params->os); + image_set_arch (hdr, params->arch); + image_set_type (hdr, params->type); + image_set_comp (hdr, params->comp); + + image_set_name (hdr, params->imagename); + + checksum = crc32 (0, (const unsigned char *)hdr, + sizeof(image_header_t)); + + image_set_hcrc (hdr, checksum); +} + +/* + * Default image type parameters definition + */ +static struct image_type_params defimage_params = { + .name = "Default Image support", + .header_size = sizeof(image_header_t), + .hdr = (void*)&header, + .check_image_type = image_check_image_types, + .verify_header = image_verify_header, + .print_header = image_print_contents, + .set_header = image_set_header, + .check_params = image_check_params, +}; + +void init_default_image_type (void) +{ + mkimage_register (&defimage_params); +} diff --git a/tools/fit_image.c b/tools/fit_image.c new file mode 100644 index 000000000..d1e612fec --- /dev/null +++ b/tools/fit_image.c @@ -0,0 +1,212 @@ +/* + * (C) Copyright 2008 Semihalf + * + * (C) Copyright 2000-2004 + * DENX Software Engineering + * Wolfgang Denk, wd@denx.de + * + * Updated-by: Prafulla Wadaskar + * FIT image specific code abstracted from mkimage.c + * some functions added to address abstraction + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include "mkimage.h" +#include +#include + +static image_header_t header; + +static int fit_verify_header (unsigned char *ptr, int image_size, + struct mkimage_params *params) +{ + return fdt_check_header ((void *)ptr); +} + +static int fit_check_image_types (uint8_t type) +{ + if (type == IH_TYPE_FLATDT) + return EXIT_SUCCESS; + else + return EXIT_FAILURE; +} + +/** + * fit_handle_file - main FIT file processing function + * + * fit_handle_file() runs dtc to convert .its to .itb, includes + * binary data, updates timestamp property and calculates hashes. + * + * datafile - .its file + * imagefile - .itb file + * + * returns: + * only on success, otherwise calls exit (EXIT_FAILURE); + */ +static int fit_handle_file (struct mkimage_params *params) +{ + char tmpfile[MKIMAGE_MAX_TMPFILE_LEN]; + char cmd[MKIMAGE_MAX_DTC_CMDLINE_LEN]; + int tfd; + struct stat sbuf; + unsigned char *ptr; + + /* Flattened Image Tree (FIT) format handling */ + debug ("FIT format handling\n"); + + /* call dtc to include binary properties into the tmp file */ + if (strlen (params->imagefile) + + strlen (MKIMAGE_TMPFILE_SUFFIX) + 1 > sizeof (tmpfile)) { + fprintf (stderr, "%s: Image file name (%s) too long, " + "can't create tmpfile", + params->imagefile, params->cmdname); + return (EXIT_FAILURE); + } + sprintf (tmpfile, "%s%s", params->imagefile, MKIMAGE_TMPFILE_SUFFIX); + + /* dtc -I dts -O -p 200 datafile > tmpfile */ + sprintf (cmd, "%s %s %s > %s", + MKIMAGE_DTC, params->dtc, params->datafile, tmpfile); + debug ("Trying to execute \"%s\"\n", cmd); + if (system (cmd) == -1) { + fprintf (stderr, "%s: system(%s) failed: %s\n", + params->cmdname, cmd, strerror(errno)); + unlink (tmpfile); + return (EXIT_FAILURE); + } + + /* load FIT blob into memory */ + tfd = open (tmpfile, O_RDWR|O_BINARY); + + if (tfd < 0) { + fprintf (stderr, "%s: Can't open %s: %s\n", + params->cmdname, tmpfile, strerror(errno)); + unlink (tmpfile); + return (EXIT_FAILURE); + } + + if (fstat (tfd, &sbuf) < 0) { + fprintf (stderr, "%s: Can't stat %s: %s\n", + params->cmdname, tmpfile, strerror(errno)); + unlink (tmpfile); + return (EXIT_FAILURE); + } + + ptr = mmap (0, sbuf.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, + tfd, 0); + if (ptr == MAP_FAILED) { + fprintf (stderr, "%s: Can't read %s: %s\n", + params->cmdname, tmpfile, strerror(errno)); + unlink (tmpfile); + return (EXIT_FAILURE); + } + + /* check if ptr has a valid blob */ + if (fdt_check_header (ptr)) { + fprintf (stderr, "%s: Invalid FIT blob\n", params->cmdname); + unlink (tmpfile); + return (EXIT_FAILURE); + } + + /* set hashes for images in the blob */ + if (fit_set_hashes (ptr)) { + fprintf (stderr, "%s Can't add hashes to FIT blob", + params->cmdname); + unlink (tmpfile); + return (EXIT_FAILURE); + } + + /* add a timestamp at offset 0 i.e., root */ + if (fit_set_timestamp (ptr, 0, sbuf.st_mtime)) { + fprintf (stderr, "%s: Can't add image timestamp\n", + params->cmdname); + unlink (tmpfile); + return (EXIT_FAILURE); + } + debug ("Added timestamp successfully\n"); + + munmap ((void *)ptr, sbuf.st_size); + close (tfd); + + if (rename (tmpfile, params->imagefile) == -1) { + fprintf (stderr, "%s: Can't rename %s to %s: %s\n", + params->cmdname, tmpfile, params->imagefile, + strerror (errno)); + unlink (tmpfile); + unlink (params->imagefile); + return (EXIT_FAILURE); + } + return (EXIT_SUCCESS); +} + +static void fit_set_header (void *ptr, struct stat *sbuf, int ifd, + struct mkimage_params *params) +{ + uint32_t checksum; + + image_header_t * hdr = (image_header_t *)ptr; + + checksum = crc32 (0, + (const unsigned char *)(ptr + + sizeof(image_header_t)), + sbuf->st_size - sizeof(image_header_t)); + + /* Build new header */ + image_set_magic (hdr, IH_MAGIC); + image_set_time (hdr, sbuf->st_mtime); + image_set_size (hdr, sbuf->st_size - sizeof(image_header_t)); + image_set_load (hdr, params->addr); + image_set_ep (hdr, params->ep); + image_set_dcrc (hdr, checksum); + image_set_os (hdr, params->os); + image_set_arch (hdr, params->arch); + image_set_type (hdr, params->type); + image_set_comp (hdr, params->comp); + + image_set_name (hdr, params->imagename); + + checksum = crc32 (0, (const unsigned char *)hdr, + sizeof(image_header_t)); + + image_set_hcrc (hdr, checksum); +} + +static int fit_check_params (struct mkimage_params *params) +{ + return ((params->dflag && (params->fflag || params->lflag)) || + (params->fflag && (params->dflag || params->lflag)) || + (params->lflag && (params->dflag || params->fflag))); +} + +static struct image_type_params fitimage_params = { + .name = "FIT Image support", + .header_size = sizeof(image_header_t), + .hdr = (void*)&header, + .verify_header = fit_verify_header, + .print_header = fit_print_contents, + .check_image_type = fit_check_image_types, + .fflag_handle = fit_handle_file, + .set_header = fit_set_header, + .check_params = fit_check_params, +}; + +void init_fit_image_type (void) +{ + mkimage_register (&fitimage_params); +} diff --git a/tools/mkimage.c b/tools/mkimage.c index b0c02ebcf..c43b20772 100644 --- a/tools/mkimage.c +++ b/tools/mkimage.c @@ -1,7 +1,7 @@ /* * (C) Copyright 2008 Semihalf * - * (C) Copyright 2000-2004 + * (C) Copyright 2000-2009 * DENX Software Engineering * Wolfgang Denk, wd@denx.de * @@ -23,126 +23,223 @@ #include "mkimage.h" #include -#include -static void copy_file (int, const char *, int); -static void usage (void); -static int image_verify_header (char *, int); -static void fit_handle_file (void); +static void copy_file(int, const char *, int); +static void usage(void); -char *datafile; -char *imagefile; -char *cmdname; +/* image_type_params link list to maintain registered image type supports */ +struct image_type_params *mkimage_tparams = NULL; -int dflag = 0; -int eflag = 0; -int fflag = 0; -int lflag = 0; -int vflag = 0; -int xflag = 0; -int opt_os = IH_OS_LINUX; -int opt_arch = IH_ARCH_PPC; -int opt_type = IH_TYPE_KERNEL; -int opt_comp = IH_COMP_GZIP; -char *opt_dtc = MKIMAGE_DEFAULT_DTC_OPTIONS; +/* parameters initialized by core will be used by the image type code */ +struct mkimage_params params = { + .os = IH_OS_LINUX, + .arch = IH_ARCH_PPC, + .type = IH_TYPE_KERNEL, + .comp = IH_COMP_GZIP, + .dtc = MKIMAGE_DEFAULT_DTC_OPTIONS, +}; -image_header_t header; -image_header_t *hdr = &header; +/* + * mkimage_register - + * + * It is used to register respective image generation/list support to the + * mkimage core + * + * the input struct image_type_params is checked and appended to the link + * list, if the input structure is already registered, error + */ +void mkimage_register (struct image_type_params *tparams) +{ + struct image_type_params **tp; + + if (!tparams) { + fprintf (stderr, "%s: %s: Null input\n", + params.cmdname, __FUNCTION__); + exit (EXIT_FAILURE); + } + + /* scan the linked list, check for registry and point the last one */ + for (tp = &mkimage_tparams; *tp != NULL; tp = &(*tp)->next) { + if (!strcmp((*tp)->name, tparams->name)) { + fprintf (stderr, "%s: %s already registered\n", + params.cmdname, tparams->name); + return; + } + } + + /* add input struct entry at the end of link list */ + *tp = tparams; + /* mark input entry as last entry in the link list */ + tparams->next = NULL; + + debug ("Registered %s\n", tparams->name); +} + +/* + * mkimage_get_type - + * + * It scans all registers image type supports + * checks the input type_id for each supported image type + * + * if successful, + * returns respective image_type_params pointer if success + * if input type_id is not supported by any of image_type_support + * returns NULL + */ +struct image_type_params *mkimage_get_type(int type) +{ + struct image_type_params *curr; + + for (curr = mkimage_tparams; curr != NULL; curr = curr->next) { + if (curr->check_image_type) { + if (!curr->check_image_type (type)) + return curr; + } + } + return NULL; +} + +/* + * mkimage_verify_print_header - + * + * It scans mkimage_tparams link list, + * verifies image_header for each supported image type + * if verification is successful, prints respective header + * + * returns negative if input image format does not match with any of + * supported image types + */ +int mkimage_verify_print_header (void *ptr, struct stat *sbuf) +{ + int retval = -1; + struct image_type_params *curr; + + for (curr = mkimage_tparams; curr != NULL; curr = curr->next ) { + if (curr->verify_header) { + retval = curr->verify_header ( + (unsigned char *)ptr, sbuf->st_size, + ¶ms); + + if (retval == 0) { + /* + * Print the image information + * if verify is successful + */ + if (curr->print_header) + curr->print_header (ptr); + else { + fprintf (stderr, + "%s: print_header undefined for %s\n", + params.cmdname, curr->name); + } + break; + } + } + } + return retval; +} int main (int argc, char **argv) { int ifd = -1; - uint32_t checksum; - uint32_t addr; - uint32_t ep; struct stat sbuf; unsigned char *ptr; - char *name = ""; int retval = 0; + struct image_type_params *tparams = NULL; - cmdname = *argv; + /* Init FIT image generation/list support */ + init_fit_image_type (); + /* Init Default image generation/list support */ + init_default_image_type (); - addr = ep = 0; + params.cmdname = *argv; + params.addr = params.ep = 0; while (--argc > 0 && **++argv == '-') { while (*++*argv) { switch (**argv) { case 'l': - lflag = 1; + params.lflag = 1; break; case 'A': if ((--argc <= 0) || - (opt_arch = genimg_get_arch_id (*++argv)) < 0) + (params.arch = + genimg_get_arch_id (*++argv)) < 0) usage (); goto NXTARG; case 'C': if ((--argc <= 0) || - (opt_comp = genimg_get_comp_id (*++argv)) < 0) + (params.comp = + genimg_get_comp_id (*++argv)) < 0) usage (); goto NXTARG; case 'D': if (--argc <= 0) usage (); - opt_dtc = *++argv; + params.dtc = *++argv; goto NXTARG; case 'O': if ((--argc <= 0) || - (opt_os = genimg_get_os_id (*++argv)) < 0) + (params.os = + genimg_get_os_id (*++argv)) < 0) usage (); goto NXTARG; case 'T': if ((--argc <= 0) || - (opt_type = genimg_get_type_id (*++argv)) < 0) + (params.type = + genimg_get_type_id (*++argv)) < 0) usage (); goto NXTARG; case 'a': if (--argc <= 0) usage (); - addr = strtoul (*++argv, (char **)&ptr, 16); + params.addr = strtoul (*++argv, + (char **)&ptr, 16); if (*ptr) { fprintf (stderr, "%s: invalid load address %s\n", - cmdname, *argv); + params.cmdname, *argv); exit (EXIT_FAILURE); } goto NXTARG; case 'd': if (--argc <= 0) usage (); - datafile = *++argv; - dflag = 1; + params.datafile = *++argv; + params.dflag = 1; goto NXTARG; case 'e': if (--argc <= 0) usage (); - ep = strtoul (*++argv, (char **)&ptr, 16); + params.ep = strtoul (*++argv, + (char **)&ptr, 16); if (*ptr) { fprintf (stderr, "%s: invalid entry point %s\n", - cmdname, *argv); + params.cmdname, *argv); exit (EXIT_FAILURE); } - eflag = 1; + params.eflag = 1; goto NXTARG; case 'f': if (--argc <= 0) usage (); - datafile = *++argv; - fflag = 1; + params.datafile = *++argv; + params.fflag = 1; goto NXTARG; case 'n': if (--argc <= 0) usage (); - name = *++argv; + params.imagename = *++argv; goto NXTARG; case 'v': - vflag++; + params.vflag++; break; case 'x': - xflag++; + params.xflag++; break; default: usage (); @@ -151,91 +248,112 @@ main (int argc, char **argv) NXTARG: ; } - if ((argc != 1) || - (dflag && (fflag || lflag)) || - (fflag && (dflag || lflag)) || - (lflag && (dflag || fflag))) - usage(); + if (argc != 1) + usage (); - if (!eflag) { - ep = addr; + /* set tparams as per input type_id */ + tparams = mkimage_get_type(params.type); + if (tparams == NULL) { + fprintf (stderr, "%s: unsupported type %s\n", + params.cmdname, genimg_get_type_name(params.type)); + exit (EXIT_FAILURE); + } + + /* + * check the passed arguments parameters meets the requirements + * as per image type to be generated/listed + */ + if (tparams->check_params) + if (tparams->check_params (¶ms)) + usage (); + + if (!params.eflag) { + params.ep = params.addr; /* If XIP, entry point must be after the U-Boot header */ - if (xflag) - ep += image_get_header_size (); + if (params.xflag) + params.ep += tparams->header_size; } /* * If XIP, ensure the entry point is equal to the load address plus * the size of the U-Boot header. */ - if (xflag) { - if (ep != addr + image_get_header_size ()) { + if (params.xflag) { + if (params.ep != params.addr + tparams->header_size) { fprintf (stderr, "%s: For XIP, the entry point must be the load addr + %lu\n", - cmdname, - (unsigned long)image_get_header_size ()); + params.cmdname, + (unsigned long)tparams->header_size); exit (EXIT_FAILURE); } } - imagefile = *argv; + params.imagefile = *argv; - if (!fflag){ - if (lflag) { - ifd = open (imagefile, O_RDONLY|O_BINARY); + if (!params.fflag){ + if (params.lflag) { + ifd = open (params.imagefile, O_RDONLY|O_BINARY); } else { - ifd = open (imagefile, + ifd = open (params.imagefile, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, 0666); } if (ifd < 0) { fprintf (stderr, "%s: Can't open %s: %s\n", - cmdname, imagefile, strerror(errno)); + params.cmdname, params.imagefile, + strerror(errno)); exit (EXIT_FAILURE); } } - if (lflag) { + if (params.lflag) { /* * list header information of existing image */ if (fstat(ifd, &sbuf) < 0) { fprintf (stderr, "%s: Can't stat %s: %s\n", - cmdname, imagefile, strerror(errno)); + params.cmdname, params.imagefile, + strerror(errno)); exit (EXIT_FAILURE); } - if ((unsigned)sbuf.st_size < image_get_header_size ()) { + if ((unsigned)sbuf.st_size < tparams->header_size) { fprintf (stderr, - "%s: Bad size: \"%s\" is no valid image\n", - cmdname, imagefile); + "%s: Bad size: \"%s\" is not valid image\n", + params.cmdname, params.imagefile); exit (EXIT_FAILURE); } ptr = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, ifd, 0); if (ptr == MAP_FAILED) { fprintf (stderr, "%s: Can't read %s: %s\n", - cmdname, imagefile, strerror(errno)); + params.cmdname, params.imagefile, + strerror(errno)); exit (EXIT_FAILURE); } - if (!(retval = fdt_check_header (ptr))) { - /* FIT image */ - fit_print_contents (ptr); - } else if (!(retval = image_verify_header ((char *)ptr, - sbuf.st_size))) { - /* old-style image */ - image_print_contents ((image_header_t *)ptr); - } + /* + * scan through mkimage registry for all supported image types + * and verify the input image file header for match + * Print the image information for matched image type + * Returns the error code if not matched + */ + retval = mkimage_verify_print_header (ptr, &sbuf); (void) munmap((void *)ptr, sbuf.st_size); (void) close (ifd); exit (retval); - } else if (fflag) { - /* Flattened Image Tree (FIT) format handling */ - debug ("FIT format handling\n"); - fit_handle_file (); + } else if (params.fflag) { + if (tparams->fflag_handle) + /* + * in some cases, some additional processing needs + * to be done if fflag is defined + * + * For ex. fit_handle_file for Fit file support + */ + retval = tparams->fflag_handle(¶ms); + exit (retval); } @@ -244,16 +362,17 @@ NXTARG: ; * * write dummy header, to be fixed later */ - memset (hdr, 0, image_get_header_size ()); + memset (tparams->hdr, 0, tparams->header_size); - if (write(ifd, hdr, image_get_header_size ()) != image_get_header_size ()) { + if (write(ifd, tparams->hdr, tparams->header_size) + != tparams->header_size) { fprintf (stderr, "%s: Write error on %s: %s\n", - cmdname, imagefile, strerror(errno)); + params.cmdname, params.imagefile, strerror(errno)); exit (EXIT_FAILURE); } - if (opt_type == IH_TYPE_MULTI || opt_type == IH_TYPE_SCRIPT) { - char *file = datafile; + if (params.type == IH_TYPE_MULTI || params.type == IH_TYPE_SCRIPT) { + char *file = params.datafile; uint32_t size; for (;;) { @@ -266,7 +385,7 @@ NXTARG: ; if (stat (file, &sbuf) < 0) { fprintf (stderr, "%s: Can't stat %s: %s\n", - cmdname, file, strerror(errno)); + params.cmdname, file, strerror(errno)); exit (EXIT_FAILURE); } size = cpu_to_uimage (sbuf.st_size); @@ -276,7 +395,8 @@ NXTARG: ; if (write(ifd, (char *)&size, sizeof(size)) != sizeof(size)) { fprintf (stderr, "%s: Write error on %s: %s\n", - cmdname, imagefile, strerror(errno)); + params.cmdname, params.imagefile, + strerror(errno)); exit (EXIT_FAILURE); } @@ -292,7 +412,7 @@ NXTARG: ; } } - file = datafile; + file = params.datafile; for (;;) { char *sep = strchr(file, ':'); @@ -307,11 +427,14 @@ NXTARG: ; } } } else { - copy_file (ifd, datafile, 0); + copy_file (ifd, params.datafile, 0); } /* We're a bit of paranoid */ -#if defined(_POSIX_SYNCHRONIZED_IO) && !defined(__sun__) && !defined(__FreeBSD__) && !defined(__APPLE__) +#if defined(_POSIX_SYNCHRONIZED_IO) && \ + !defined(__sun__) && \ + !defined(__FreeBSD__) && \ + !defined(__APPLE__) (void) fdatasync (ifd); #else (void) fsync (ifd); @@ -319,50 +442,42 @@ NXTARG: ; if (fstat(ifd, &sbuf) < 0) { fprintf (stderr, "%s: Can't stat %s: %s\n", - cmdname, imagefile, strerror(errno)); + params.cmdname, params.imagefile, strerror(errno)); exit (EXIT_FAILURE); } ptr = mmap(0, sbuf.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, ifd, 0); if (ptr == MAP_FAILED) { fprintf (stderr, "%s: Can't map %s: %s\n", - cmdname, imagefile, strerror(errno)); + params.cmdname, params.imagefile, strerror(errno)); exit (EXIT_FAILURE); } - hdr = (image_header_t *)ptr; + /* Setup the image header as per input image type*/ + if (tparams->set_header) + tparams->set_header (ptr, &sbuf, ifd, ¶ms); + else { + fprintf (stderr, "%s: Can't set header for %s: %s\n", + params.cmdname, tparams->name, strerror(errno)); + exit (EXIT_FAILURE); + } - checksum = crc32 (0, - (const unsigned char *)(ptr + - image_get_header_size ()), - sbuf.st_size - image_get_header_size () - ); - - /* Build new header */ - image_set_magic (hdr, IH_MAGIC); - image_set_time (hdr, sbuf.st_mtime); - image_set_size (hdr, sbuf.st_size - image_get_header_size ()); - image_set_load (hdr, addr); - image_set_ep (hdr, ep); - image_set_dcrc (hdr, checksum); - image_set_os (hdr, opt_os); - image_set_arch (hdr, opt_arch); - image_set_type (hdr, opt_type); - image_set_comp (hdr, opt_comp); - - image_set_name (hdr, name); - - checksum = crc32 (0, (const unsigned char *)hdr, - image_get_header_size ()); - - image_set_hcrc (hdr, checksum); - - image_print_contents (hdr); + /* Print the image information by processing image header */ + if (tparams->print_header) + tparams->print_header (ptr); + else { + fprintf (stderr, "%s: Can't print header for %s: %s\n", + params.cmdname, tparams->name, strerror(errno)); + exit (EXIT_FAILURE); + } (void) munmap((void *)ptr, sbuf.st_size); /* We're a bit of paranoid */ -#if defined(_POSIX_SYNCHRONIZED_IO) && !defined(__sun__) && !defined(__FreeBSD__) && !defined(__APPLE__) +#if defined(_POSIX_SYNCHRONIZED_IO) && \ + !defined(__sun__) && \ + !defined(__FreeBSD__) && \ + !defined(__APPLE__) (void) fdatasync (ifd); #else (void) fsync (ifd); @@ -370,7 +485,7 @@ NXTARG: ; if (close(ifd)) { fprintf (stderr, "%s: Write error on %s: %s\n", - cmdname, imagefile, strerror(errno)); + params.cmdname, params.imagefile, strerror(errno)); exit (EXIT_FAILURE); } @@ -387,31 +502,32 @@ copy_file (int ifd, const char *datafile, int pad) int zero = 0; int offset = 0; int size; + struct image_type_params *tparams = mkimage_get_type (params.type); - if (vflag) { + if (params.vflag) { fprintf (stderr, "Adding Image %s\n", datafile); } if ((dfd = open(datafile, O_RDONLY|O_BINARY)) < 0) { fprintf (stderr, "%s: Can't open %s: %s\n", - cmdname, datafile, strerror(errno)); + params.cmdname, datafile, strerror(errno)); exit (EXIT_FAILURE); } if (fstat(dfd, &sbuf) < 0) { fprintf (stderr, "%s: Can't stat %s: %s\n", - cmdname, datafile, strerror(errno)); + params.cmdname, datafile, strerror(errno)); exit (EXIT_FAILURE); } ptr = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, dfd, 0); if (ptr == MAP_FAILED) { fprintf (stderr, "%s: Can't read %s: %s\n", - cmdname, datafile, strerror(errno)); + params.cmdname, datafile, strerror(errno)); exit (EXIT_FAILURE); } - if (xflag) { + if (params.xflag) { unsigned char *p = NULL; /* * XIP: do not append the image_header_t at the @@ -419,29 +535,29 @@ copy_file (int ifd, const char *datafile, int pad) * reserved for it. */ - if ((unsigned)sbuf.st_size < image_get_header_size ()) { + if ((unsigned)sbuf.st_size < tparams->header_size) { fprintf (stderr, "%s: Bad size: \"%s\" is too small for XIP\n", - cmdname, datafile); + params.cmdname, datafile); exit (EXIT_FAILURE); } - for (p = ptr; p < ptr + image_get_header_size (); p++) { + for (p = ptr; p < ptr + tparams->header_size; p++) { if ( *p != 0xff ) { fprintf (stderr, "%s: Bad file: \"%s\" has invalid buffer for XIP\n", - cmdname, datafile); + params.cmdname, datafile); exit (EXIT_FAILURE); } } - offset = image_get_header_size (); + offset = tparams->header_size; } size = sbuf.st_size - offset; if (write(ifd, ptr + offset, size) != size) { fprintf (stderr, "%s: Write error on %s: %s\n", - cmdname, imagefile, strerror(errno)); + params.cmdname, params.imagefile, strerror(errno)); exit (EXIT_FAILURE); } @@ -449,7 +565,8 @@ copy_file (int ifd, const char *datafile, int pad) if (write(ifd, (char *)&zero, 4-tail) != 4-tail) { fprintf (stderr, "%s: Write error on %s: %s\n", - cmdname, imagefile, strerror(errno)); + params.cmdname, params.imagefile, + strerror(errno)); exit (EXIT_FAILURE); } } @@ -463,7 +580,7 @@ usage () { fprintf (stderr, "Usage: %s -l image\n" " -l ==> list image header information\n", - cmdname); + params.cmdname); fprintf (stderr, " %s [-x] -A arch -O os -T type -C comp " "-a addr -e ep -n name -d data_file[:data_file...] image\n" " -A ==> set architecture to 'arch'\n" @@ -475,157 +592,9 @@ usage () " -n ==> set image name to 'name'\n" " -d ==> use image data from 'datafile'\n" " -x ==> set XIP (execute in place)\n", - cmdname); + params.cmdname); fprintf (stderr, " %s [-D dtc_options] -f fit-image.its fit-image\n", - cmdname); + params.cmdname); exit (EXIT_FAILURE); } - -static int -image_verify_header (char *ptr, int image_size) -{ - int len; - const unsigned char *data; - uint32_t checksum; - image_header_t header; - image_header_t *hdr = &header; - - /* - * create copy of header so that we can blank out the - * checksum field for checking - this can't be done - * on the PROT_READ mapped data. - */ - memcpy (hdr, ptr, sizeof(image_header_t)); - - if (be32_to_cpu(hdr->ih_magic) != IH_MAGIC) { - fprintf (stderr, - "%s: Bad Magic Number: \"%s\" is no valid image\n", - cmdname, imagefile); - return -FDT_ERR_BADMAGIC; - } - - data = (const unsigned char *)hdr; - len = sizeof(image_header_t); - - checksum = be32_to_cpu(hdr->ih_hcrc); - hdr->ih_hcrc = cpu_to_be32(0); /* clear for re-calculation */ - - if (crc32 (0, data, len) != checksum) { - fprintf (stderr, - "%s: ERROR: \"%s\" has bad header checksum!\n", - cmdname, imagefile); - return -FDT_ERR_BADSTATE; - } - - data = (const unsigned char *)ptr + sizeof(image_header_t); - len = image_size - sizeof(image_header_t) ; - - if (crc32 (0, data, len) != be32_to_cpu(hdr->ih_dcrc)) { - fprintf (stderr, - "%s: ERROR: \"%s\" has corrupted data!\n", - cmdname, imagefile); - return -FDT_ERR_BADSTRUCTURE; - } - return 0; -} - -/** - * fit_handle_file - main FIT file processing function - * - * fit_handle_file() runs dtc to convert .its to .itb, includes - * binary data, updates timestamp property and calculates hashes. - * - * datafile - .its file - * imagefile - .itb file - * - * returns: - * only on success, otherwise calls exit (EXIT_FAILURE); - */ -static void fit_handle_file (void) -{ - char tmpfile[MKIMAGE_MAX_TMPFILE_LEN]; - char cmd[MKIMAGE_MAX_DTC_CMDLINE_LEN]; - int tfd; - struct stat sbuf; - unsigned char *ptr; - - /* call dtc to include binary properties into the tmp file */ - if (strlen (imagefile) + strlen (MKIMAGE_TMPFILE_SUFFIX) + 1 > - sizeof (tmpfile)) { - fprintf (stderr, "%s: Image file name (%s) too long, " - "can't create tmpfile", - imagefile, cmdname); - exit (EXIT_FAILURE); - } - sprintf (tmpfile, "%s%s", imagefile, MKIMAGE_TMPFILE_SUFFIX); - - /* dtc -I dts -O -p 200 datafile > tmpfile */ - sprintf (cmd, "%s %s %s > %s", - MKIMAGE_DTC, opt_dtc, datafile, tmpfile); - debug ("Trying to execute \"%s\"\n", cmd); - if (system (cmd) == -1) { - fprintf (stderr, "%s: system(%s) failed: %s\n", - cmdname, cmd, strerror(errno)); - unlink (tmpfile); - exit (EXIT_FAILURE); - } - - /* load FIT blob into memory */ - tfd = open (tmpfile, O_RDWR|O_BINARY); - - if (tfd < 0) { - fprintf (stderr, "%s: Can't open %s: %s\n", - cmdname, tmpfile, strerror(errno)); - unlink (tmpfile); - exit (EXIT_FAILURE); - } - - if (fstat (tfd, &sbuf) < 0) { - fprintf (stderr, "%s: Can't stat %s: %s\n", - cmdname, tmpfile, strerror(errno)); - unlink (tmpfile); - exit (EXIT_FAILURE); - } - - ptr = mmap (0, sbuf.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, tfd, 0); - if (ptr == MAP_FAILED) { - fprintf (stderr, "%s: Can't read %s: %s\n", - cmdname, tmpfile, strerror(errno)); - unlink (tmpfile); - exit (EXIT_FAILURE); - } - - /* check if ptr has a valid blob */ - if (fdt_check_header (ptr)) { - fprintf (stderr, "%s: Invalid FIT blob\n", cmdname); - unlink (tmpfile); - exit (EXIT_FAILURE); - } - - /* set hashes for images in the blob */ - if (fit_set_hashes (ptr)) { - fprintf (stderr, "%s Can't add hashes to FIT blob", cmdname); - unlink (tmpfile); - exit (EXIT_FAILURE); - } - - /* add a timestamp at offset 0 i.e., root */ - if (fit_set_timestamp (ptr, 0, sbuf.st_mtime)) { - fprintf (stderr, "%s: Can't add image timestamp\n", cmdname); - unlink (tmpfile); - exit (EXIT_FAILURE); - } - debug ("Added timestamp successfully\n"); - - munmap ((void *)ptr, sbuf.st_size); - close (tfd); - - if (rename (tmpfile, imagefile) == -1) { - fprintf (stderr, "%s: Can't rename %s to %s: %s\n", - cmdname, tmpfile, imagefile, strerror (errno)); - unlink (tmpfile); - unlink (imagefile); - exit (EXIT_FAILURE); - } -} diff --git a/tools/mkimage.h b/tools/mkimage.h index c077dc955..120970fc6 100644 --- a/tools/mkimage.h +++ b/tools/mkimage.h @@ -19,6 +19,9 @@ * MA 02111-1307 USA */ +#ifndef _MKIIMAGE_H_ +#define _MKIIMAGE_H_ + #include "os_support.h" #include #include @@ -31,7 +34,7 @@ #include #include "fdt_host.h" -#define MKIMAGE_DEBUG +#undef MKIMAGE_DEBUG #ifdef MKIMAGE_DEBUG #define debug(fmt,args...) printf (fmt ,##args) @@ -44,3 +47,99 @@ #define MKIMAGE_DEFAULT_DTC_OPTIONS "-I dts -O dtb -p 500" #define MKIMAGE_MAX_DTC_CMDLINE_LEN 512 #define MKIMAGE_DTC "dtc" /* assume dtc is in $PATH */ + +/* + * This structure defines all such variables those are initialized by + * mkimage main core and need to be referred by image type specific + * functions + */ +struct mkimage_params { + int dflag; + int eflag; + int fflag; + int lflag; + int vflag; + int xflag; + int os; + int arch; + int type; + int comp; + char *dtc; + unsigned int addr; + unsigned int ep; + char *imagename; + char *datafile; + char *imagefile; + char *cmdname; +}; + +/* + * image type specific variables and callback functions + */ +struct image_type_params { + /* name is an identification tag string for added support */ + char *name; + /* + * header size is local to the specific image type to be supported, + * mkimage core treats this as number of bytes + */ + uint32_t header_size; + /* Image type header pointer */ + void *hdr; + /* + * There are several arguments that are passed on the command line + * and are registered as flags in mkimage_params structure. + * This callback function can be used to check the passed arguments + * are in-lined with the image type to be supported + * + * Returns 1 if parameter check is successful + */ + int (*check_params) (struct mkimage_params *); + /* + * This function is used by list command (i.e. mkimage -l ) + * image type verification code must be put here + * + * Returns 0 if image header verification is successful + * otherwise, returns respective negative error codes + */ + int (*verify_header) (unsigned char *, int, struct mkimage_params *); + /* Prints image information abstracting from image header */ + void (*print_header) (void *); + /* + * The header or image contents need to be set as per image type to + * be generated using this callback function. + * further output file post processing (for ex. checksum calculation, + * padding bytes etc..) can also be done in this callback function. + */ + void (*set_header) (void *, struct stat *, int, + struct mkimage_params *); + /* + * Some image generation support for ex (default image type) supports + * more than one type_ids, this callback function is used to check + * whether input (-T ) is supported by registered image + * generation/list low level code + */ + int (*check_image_type) (uint8_t); + /* This callback function will be executed if fflag is defined */ + int (*fflag_handle) (struct mkimage_params *); + /* pointer to the next registered entry in linked list */ + struct image_type_params *next; +}; + +/* + * Exported functions + */ +void mkimage_register (struct image_type_params *tparams); + +/* + * There is a c file associated with supported image type low level code + * for ex. default_image.c, fit_image.c + * init is the only function referred by mkimage core. + * to avoid a single lined header file, you can define them here + * + * Supported image types init functions + */ +void init_default_image_type (void); +void init_fit_image_type (void); + +#endif /* _MKIIMAGE_H_ */