15b1d7137Swdenk /* 29d25438fSBartlomiej Sieka * (C) Copyright 2008 Semihalf 39d25438fSBartlomiej Sieka * 40c852a28Swdenk * (C) Copyright 2000-2004 55b1d7137Swdenk * DENX Software Engineering 65b1d7137Swdenk * Wolfgang Denk, wd@denx.de 70c852a28Swdenk * 80c852a28Swdenk * This program is free software; you can redistribute it and/or 90c852a28Swdenk * modify it under the terms of the GNU General Public License as 100c852a28Swdenk * published by the Free Software Foundation; either version 2 of 110c852a28Swdenk * the License, or (at your option) any later version. 120c852a28Swdenk * 130c852a28Swdenk * This program is distributed in the hope that it will be useful, 140c852a28Swdenk * but WITHOUT ANY WARRANTY; without even the implied warranty of 150c852a28Swdenk * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 160c852a28Swdenk * GNU General Public License for more details. 170c852a28Swdenk * 180c852a28Swdenk * You should have received a copy of the GNU General Public License 190c852a28Swdenk * along with this program; if not, write to the Free Software 200c852a28Swdenk * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 210c852a28Swdenk * MA 02111-1307 USA 225b1d7137Swdenk */ 235b1d7137Swdenk 24b97a2a0aSMarian Balakowicz #include "mkimage.h" 255b1d7137Swdenk #include <image.h> 26*449609f5SPrafulla Wadaskar #include <u-boot/crc.h> 275b1d7137Swdenk 285b1d7137Swdenk static void copy_file (int, const char *, int); 295b1d7137Swdenk static void usage (void); 30f7644c0bSPrafulla Wadaskar static int image_verify_header (char *, int); 319d25438fSBartlomiej Sieka static void fit_handle_file (void); 325b1d7137Swdenk 335b1d7137Swdenk char *datafile; 345b1d7137Swdenk char *imagefile; 35570abb0aSMarian Balakowicz char *cmdname; 365b1d7137Swdenk 375b1d7137Swdenk int dflag = 0; 385b1d7137Swdenk int eflag = 0; 399d25438fSBartlomiej Sieka int fflag = 0; 405b1d7137Swdenk int lflag = 0; 415b1d7137Swdenk int vflag = 0; 425b1d7137Swdenk int xflag = 0; 435b1d7137Swdenk int opt_os = IH_OS_LINUX; 44b97a2a0aSMarian Balakowicz int opt_arch = IH_ARCH_PPC; 455b1d7137Swdenk int opt_type = IH_TYPE_KERNEL; 465b1d7137Swdenk int opt_comp = IH_COMP_GZIP; 479d25438fSBartlomiej Sieka char *opt_dtc = MKIMAGE_DEFAULT_DTC_OPTIONS; 485b1d7137Swdenk 495b1d7137Swdenk image_header_t header; 505b1d7137Swdenk image_header_t *hdr = &header; 515b1d7137Swdenk 525b1d7137Swdenk int 535b1d7137Swdenk main (int argc, char **argv) 545b1d7137Swdenk { 559d25438fSBartlomiej Sieka int ifd = -1; 565b1d7137Swdenk uint32_t checksum; 575b1d7137Swdenk uint32_t addr; 585b1d7137Swdenk uint32_t ep; 595b1d7137Swdenk struct stat sbuf; 605b1d7137Swdenk unsigned char *ptr; 615b1d7137Swdenk char *name = ""; 62*449609f5SPrafulla Wadaskar int retval = 0; 635b1d7137Swdenk 645b1d7137Swdenk cmdname = *argv; 655b1d7137Swdenk 665b1d7137Swdenk addr = ep = 0; 675b1d7137Swdenk 685b1d7137Swdenk while (--argc > 0 && **++argv == '-') { 695b1d7137Swdenk while (*++*argv) { 705b1d7137Swdenk switch (**argv) { 715b1d7137Swdenk case 'l': 725b1d7137Swdenk lflag = 1; 735b1d7137Swdenk break; 745b1d7137Swdenk case 'A': 755b1d7137Swdenk if ((--argc <= 0) || 76570abb0aSMarian Balakowicz (opt_arch = genimg_get_arch_id (*++argv)) < 0) 775b1d7137Swdenk usage (); 785b1d7137Swdenk goto NXTARG; 795b1d7137Swdenk case 'C': 805b1d7137Swdenk if ((--argc <= 0) || 81570abb0aSMarian Balakowicz (opt_comp = genimg_get_comp_id (*++argv)) < 0) 825b1d7137Swdenk usage (); 835b1d7137Swdenk goto NXTARG; 849d25438fSBartlomiej Sieka case 'D': 859d25438fSBartlomiej Sieka if (--argc <= 0) 869d25438fSBartlomiej Sieka usage (); 879d25438fSBartlomiej Sieka opt_dtc = *++argv; 889d25438fSBartlomiej Sieka goto NXTARG; 899d25438fSBartlomiej Sieka 905b1d7137Swdenk case 'O': 915b1d7137Swdenk if ((--argc <= 0) || 92570abb0aSMarian Balakowicz (opt_os = genimg_get_os_id (*++argv)) < 0) 935b1d7137Swdenk usage (); 945b1d7137Swdenk goto NXTARG; 955b1d7137Swdenk case 'T': 965b1d7137Swdenk if ((--argc <= 0) || 97570abb0aSMarian Balakowicz (opt_type = genimg_get_type_id (*++argv)) < 0) 985b1d7137Swdenk usage (); 995b1d7137Swdenk goto NXTARG; 1005b1d7137Swdenk 1015b1d7137Swdenk case 'a': 1025b1d7137Swdenk if (--argc <= 0) 1035b1d7137Swdenk usage (); 1045b1d7137Swdenk addr = strtoul (*++argv, (char **)&ptr, 16); 1055b1d7137Swdenk if (*ptr) { 1065b1d7137Swdenk fprintf (stderr, 1075b1d7137Swdenk "%s: invalid load address %s\n", 1085b1d7137Swdenk cmdname, *argv); 1095b1d7137Swdenk exit (EXIT_FAILURE); 1105b1d7137Swdenk } 1115b1d7137Swdenk goto NXTARG; 1125b1d7137Swdenk case 'd': 1135b1d7137Swdenk if (--argc <= 0) 1145b1d7137Swdenk usage (); 1155b1d7137Swdenk datafile = *++argv; 1165b1d7137Swdenk dflag = 1; 1175b1d7137Swdenk goto NXTARG; 1185b1d7137Swdenk case 'e': 1195b1d7137Swdenk if (--argc <= 0) 1205b1d7137Swdenk usage (); 1215b1d7137Swdenk ep = strtoul (*++argv, (char **)&ptr, 16); 1225b1d7137Swdenk if (*ptr) { 1235b1d7137Swdenk fprintf (stderr, 1245b1d7137Swdenk "%s: invalid entry point %s\n", 1255b1d7137Swdenk cmdname, *argv); 1265b1d7137Swdenk exit (EXIT_FAILURE); 1275b1d7137Swdenk } 1285b1d7137Swdenk eflag = 1; 1295b1d7137Swdenk goto NXTARG; 1309d25438fSBartlomiej Sieka case 'f': 1319d25438fSBartlomiej Sieka if (--argc <= 0) 1329d25438fSBartlomiej Sieka usage (); 1339d25438fSBartlomiej Sieka datafile = *++argv; 1349d25438fSBartlomiej Sieka fflag = 1; 1359d25438fSBartlomiej Sieka goto NXTARG; 1365b1d7137Swdenk case 'n': 1375b1d7137Swdenk if (--argc <= 0) 1385b1d7137Swdenk usage (); 1395b1d7137Swdenk name = *++argv; 1405b1d7137Swdenk goto NXTARG; 1415b1d7137Swdenk case 'v': 1425b1d7137Swdenk vflag++; 1435b1d7137Swdenk break; 1445b1d7137Swdenk case 'x': 1455b1d7137Swdenk xflag++; 1465b1d7137Swdenk break; 1475b1d7137Swdenk default: 1485b1d7137Swdenk usage (); 1495b1d7137Swdenk } 1505b1d7137Swdenk } 1515b1d7137Swdenk NXTARG: ; 1525b1d7137Swdenk } 1535b1d7137Swdenk 1549d25438fSBartlomiej Sieka if ((argc != 1) || 1559d25438fSBartlomiej Sieka (dflag && (fflag || lflag)) || 1569d25438fSBartlomiej Sieka (fflag && (dflag || lflag)) || 1579d25438fSBartlomiej Sieka (lflag && (dflag || fflag))) 1585b1d7137Swdenk usage(); 1595b1d7137Swdenk 1605b1d7137Swdenk if (!eflag) { 1615b1d7137Swdenk ep = addr; 1625b1d7137Swdenk /* If XIP, entry point must be after the U-Boot header */ 1635b1d7137Swdenk if (xflag) 164b97a2a0aSMarian Balakowicz ep += image_get_header_size (); 1655b1d7137Swdenk } 1665b1d7137Swdenk 1675b1d7137Swdenk /* 1685b1d7137Swdenk * If XIP, ensure the entry point is equal to the load address plus 1695b1d7137Swdenk * the size of the U-Boot header. 1705b1d7137Swdenk */ 1715b1d7137Swdenk if (xflag) { 172b97a2a0aSMarian Balakowicz if (ep != addr + image_get_header_size ()) { 1733577d3a3SWolfgang Denk fprintf (stderr, 1743577d3a3SWolfgang Denk "%s: For XIP, the entry point must be the load addr + %lu\n", 175a6c7ad2fSwdenk cmdname, 176b97a2a0aSMarian Balakowicz (unsigned long)image_get_header_size ()); 1775b1d7137Swdenk exit (EXIT_FAILURE); 1785b1d7137Swdenk } 1795b1d7137Swdenk } 1805b1d7137Swdenk 1815b1d7137Swdenk imagefile = *argv; 1825b1d7137Swdenk 1839d25438fSBartlomiej Sieka if (!fflag){ 1845b1d7137Swdenk if (lflag) { 185ef1464ccSwdenk ifd = open (imagefile, O_RDONLY|O_BINARY); 1865b1d7137Swdenk } else { 1879d25438fSBartlomiej Sieka ifd = open (imagefile, 1889d25438fSBartlomiej Sieka O_RDWR|O_CREAT|O_TRUNC|O_BINARY, 0666); 1895b1d7137Swdenk } 1905b1d7137Swdenk 1915b1d7137Swdenk if (ifd < 0) { 1925b1d7137Swdenk fprintf (stderr, "%s: Can't open %s: %s\n", 1935b1d7137Swdenk cmdname, imagefile, strerror(errno)); 1945b1d7137Swdenk exit (EXIT_FAILURE); 1955b1d7137Swdenk } 1969d25438fSBartlomiej Sieka } 1975b1d7137Swdenk 1985b1d7137Swdenk if (lflag) { 1995b1d7137Swdenk /* 2005b1d7137Swdenk * list header information of existing image 2015b1d7137Swdenk */ 2025b1d7137Swdenk if (fstat(ifd, &sbuf) < 0) { 2035b1d7137Swdenk fprintf (stderr, "%s: Can't stat %s: %s\n", 2045b1d7137Swdenk cmdname, imagefile, strerror(errno)); 2055b1d7137Swdenk exit (EXIT_FAILURE); 2065b1d7137Swdenk } 2075b1d7137Swdenk 208b97a2a0aSMarian Balakowicz if ((unsigned)sbuf.st_size < image_get_header_size ()) { 2095b1d7137Swdenk fprintf (stderr, 2105b1d7137Swdenk "%s: Bad size: \"%s\" is no valid image\n", 2115b1d7137Swdenk cmdname, imagefile); 2125b1d7137Swdenk exit (EXIT_FAILURE); 2135b1d7137Swdenk } 2145b1d7137Swdenk 215fa956fdeSMike Frysinger ptr = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, ifd, 0); 216fa956fdeSMike Frysinger if (ptr == MAP_FAILED) { 2175b1d7137Swdenk fprintf (stderr, "%s: Can't read %s: %s\n", 2185b1d7137Swdenk cmdname, imagefile, strerror(errno)); 2195b1d7137Swdenk exit (EXIT_FAILURE); 2205b1d7137Swdenk } 2215b1d7137Swdenk 222f7644c0bSPrafulla Wadaskar if (!(retval = fdt_check_header (ptr))) { 2239d25438fSBartlomiej Sieka /* FIT image */ 224edbed247SBartlomiej Sieka fit_print_contents (ptr); 225f7644c0bSPrafulla Wadaskar } else if (!(retval = image_verify_header ((char *)ptr, 226f7644c0bSPrafulla Wadaskar sbuf.st_size))) { 227f7644c0bSPrafulla Wadaskar /* old-style image */ 228f7644c0bSPrafulla Wadaskar image_print_contents ((image_header_t *)ptr); 2299d25438fSBartlomiej Sieka } 2305b1d7137Swdenk 2315b1d7137Swdenk (void) munmap((void *)ptr, sbuf.st_size); 2325b1d7137Swdenk (void) close (ifd); 2335b1d7137Swdenk 234f7644c0bSPrafulla Wadaskar exit (retval); 2359d25438fSBartlomiej Sieka } else if (fflag) { 2369d25438fSBartlomiej Sieka /* Flattened Image Tree (FIT) format handling */ 2379d25438fSBartlomiej Sieka debug ("FIT format handling\n"); 2389d25438fSBartlomiej Sieka fit_handle_file (); 239f7644c0bSPrafulla Wadaskar exit (retval); 2405b1d7137Swdenk } 2415b1d7137Swdenk 2425b1d7137Swdenk /* 2435b1d7137Swdenk * Must be -w then: 2445b1d7137Swdenk * 2455b1d7137Swdenk * write dummy header, to be fixed later 2465b1d7137Swdenk */ 247b97a2a0aSMarian Balakowicz memset (hdr, 0, image_get_header_size ()); 2485b1d7137Swdenk 249b97a2a0aSMarian Balakowicz if (write(ifd, hdr, image_get_header_size ()) != image_get_header_size ()) { 2505b1d7137Swdenk fprintf (stderr, "%s: Write error on %s: %s\n", 2515b1d7137Swdenk cmdname, imagefile, strerror(errno)); 2525b1d7137Swdenk exit (EXIT_FAILURE); 2535b1d7137Swdenk } 2545b1d7137Swdenk 2555b1d7137Swdenk if (opt_type == IH_TYPE_MULTI || opt_type == IH_TYPE_SCRIPT) { 2565b1d7137Swdenk char *file = datafile; 2573bb66806SWolfgang Denk uint32_t size; 2585b1d7137Swdenk 2595b1d7137Swdenk for (;;) { 2605b1d7137Swdenk char *sep = NULL; 2615b1d7137Swdenk 2625b1d7137Swdenk if (file) { 2635b1d7137Swdenk if ((sep = strchr(file, ':')) != NULL) { 2645b1d7137Swdenk *sep = '\0'; 2655b1d7137Swdenk } 2665b1d7137Swdenk 2675b1d7137Swdenk if (stat (file, &sbuf) < 0) { 2685b1d7137Swdenk fprintf (stderr, "%s: Can't stat %s: %s\n", 2695b1d7137Swdenk cmdname, file, strerror(errno)); 2705b1d7137Swdenk exit (EXIT_FAILURE); 2715b1d7137Swdenk } 2729a4daad0SMarian Balakowicz size = cpu_to_uimage (sbuf.st_size); 2735b1d7137Swdenk } else { 2745b1d7137Swdenk size = 0; 2755b1d7137Swdenk } 2765b1d7137Swdenk 2775b1d7137Swdenk if (write(ifd, (char *)&size, sizeof(size)) != sizeof(size)) { 2785b1d7137Swdenk fprintf (stderr, "%s: Write error on %s: %s\n", 2795b1d7137Swdenk cmdname, imagefile, strerror(errno)); 2805b1d7137Swdenk exit (EXIT_FAILURE); 2815b1d7137Swdenk } 2825b1d7137Swdenk 2835b1d7137Swdenk if (!file) { 2845b1d7137Swdenk break; 2855b1d7137Swdenk } 2865b1d7137Swdenk 2875b1d7137Swdenk if (sep) { 2885b1d7137Swdenk *sep = ':'; 2895b1d7137Swdenk file = sep + 1; 2905b1d7137Swdenk } else { 2915b1d7137Swdenk file = NULL; 2925b1d7137Swdenk } 2935b1d7137Swdenk } 2945b1d7137Swdenk 2955b1d7137Swdenk file = datafile; 2965b1d7137Swdenk 2975b1d7137Swdenk for (;;) { 2985b1d7137Swdenk char *sep = strchr(file, ':'); 2995b1d7137Swdenk if (sep) { 3005b1d7137Swdenk *sep = '\0'; 3015b1d7137Swdenk copy_file (ifd, file, 1); 3025b1d7137Swdenk *sep++ = ':'; 3035b1d7137Swdenk file = sep; 3045b1d7137Swdenk } else { 3055b1d7137Swdenk copy_file (ifd, file, 0); 3065b1d7137Swdenk break; 3075b1d7137Swdenk } 3085b1d7137Swdenk } 3095b1d7137Swdenk } else { 3105b1d7137Swdenk copy_file (ifd, datafile, 0); 3115b1d7137Swdenk } 3125b1d7137Swdenk 3135b1d7137Swdenk /* We're a bit of paranoid */ 3145dfaa50eSAubrey.Li #if defined(_POSIX_SYNCHRONIZED_IO) && !defined(__sun__) && !defined(__FreeBSD__) && !defined(__APPLE__) 3155b1d7137Swdenk (void) fdatasync (ifd); 3165b1d7137Swdenk #else 3175b1d7137Swdenk (void) fsync (ifd); 3185b1d7137Swdenk #endif 3195b1d7137Swdenk 3205b1d7137Swdenk if (fstat(ifd, &sbuf) < 0) { 3215b1d7137Swdenk fprintf (stderr, "%s: Can't stat %s: %s\n", 3225b1d7137Swdenk cmdname, imagefile, strerror(errno)); 3235b1d7137Swdenk exit (EXIT_FAILURE); 3245b1d7137Swdenk } 3255b1d7137Swdenk 326fa956fdeSMike Frysinger ptr = mmap(0, sbuf.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, ifd, 0); 327fa956fdeSMike Frysinger if (ptr == MAP_FAILED) { 3285b1d7137Swdenk fprintf (stderr, "%s: Can't map %s: %s\n", 3295b1d7137Swdenk cmdname, imagefile, strerror(errno)); 3305b1d7137Swdenk exit (EXIT_FAILURE); 3315b1d7137Swdenk } 3325b1d7137Swdenk 3335b1d7137Swdenk hdr = (image_header_t *)ptr; 3345b1d7137Swdenk 3355b1d7137Swdenk checksum = crc32 (0, 336*449609f5SPrafulla Wadaskar (const unsigned char *)(ptr + 337*449609f5SPrafulla Wadaskar image_get_header_size ()), 338b97a2a0aSMarian Balakowicz sbuf.st_size - image_get_header_size () 3395b1d7137Swdenk ); 3405b1d7137Swdenk 3415b1d7137Swdenk /* Build new header */ 342b97a2a0aSMarian Balakowicz image_set_magic (hdr, IH_MAGIC); 343b97a2a0aSMarian Balakowicz image_set_time (hdr, sbuf.st_mtime); 344b97a2a0aSMarian Balakowicz image_set_size (hdr, sbuf.st_size - image_get_header_size ()); 345b97a2a0aSMarian Balakowicz image_set_load (hdr, addr); 346b97a2a0aSMarian Balakowicz image_set_ep (hdr, ep); 347b97a2a0aSMarian Balakowicz image_set_dcrc (hdr, checksum); 348b97a2a0aSMarian Balakowicz image_set_os (hdr, opt_os); 349b97a2a0aSMarian Balakowicz image_set_arch (hdr, opt_arch); 350b97a2a0aSMarian Balakowicz image_set_type (hdr, opt_type); 351b97a2a0aSMarian Balakowicz image_set_comp (hdr, opt_comp); 3525b1d7137Swdenk 353b97a2a0aSMarian Balakowicz image_set_name (hdr, name); 3545b1d7137Swdenk 355*449609f5SPrafulla Wadaskar checksum = crc32 (0, (const unsigned char *)hdr, 356*449609f5SPrafulla Wadaskar image_get_header_size ()); 3575b1d7137Swdenk 358b97a2a0aSMarian Balakowicz image_set_hcrc (hdr, checksum); 3595b1d7137Swdenk 360edbed247SBartlomiej Sieka image_print_contents (hdr); 3615b1d7137Swdenk 3625b1d7137Swdenk (void) munmap((void *)ptr, sbuf.st_size); 3635b1d7137Swdenk 3645b1d7137Swdenk /* We're a bit of paranoid */ 3655dfaa50eSAubrey.Li #if defined(_POSIX_SYNCHRONIZED_IO) && !defined(__sun__) && !defined(__FreeBSD__) && !defined(__APPLE__) 3665b1d7137Swdenk (void) fdatasync (ifd); 3675b1d7137Swdenk #else 3685b1d7137Swdenk (void) fsync (ifd); 3695b1d7137Swdenk #endif 3705b1d7137Swdenk 3715b1d7137Swdenk if (close(ifd)) { 3725b1d7137Swdenk fprintf (stderr, "%s: Write error on %s: %s\n", 3735b1d7137Swdenk cmdname, imagefile, strerror(errno)); 3745b1d7137Swdenk exit (EXIT_FAILURE); 3755b1d7137Swdenk } 3765b1d7137Swdenk 3775b1d7137Swdenk exit (EXIT_SUCCESS); 3785b1d7137Swdenk } 3795b1d7137Swdenk 3805b1d7137Swdenk static void 3815b1d7137Swdenk copy_file (int ifd, const char *datafile, int pad) 3825b1d7137Swdenk { 3835b1d7137Swdenk int dfd; 3845b1d7137Swdenk struct stat sbuf; 3855b1d7137Swdenk unsigned char *ptr; 3865b1d7137Swdenk int tail; 3875b1d7137Swdenk int zero = 0; 3885b1d7137Swdenk int offset = 0; 3895b1d7137Swdenk int size; 3905b1d7137Swdenk 3915b1d7137Swdenk if (vflag) { 3925b1d7137Swdenk fprintf (stderr, "Adding Image %s\n", datafile); 3935b1d7137Swdenk } 3945b1d7137Swdenk 395ef1464ccSwdenk if ((dfd = open(datafile, O_RDONLY|O_BINARY)) < 0) { 3965b1d7137Swdenk fprintf (stderr, "%s: Can't open %s: %s\n", 3975b1d7137Swdenk cmdname, datafile, strerror(errno)); 3985b1d7137Swdenk exit (EXIT_FAILURE); 3995b1d7137Swdenk } 4005b1d7137Swdenk 4015b1d7137Swdenk if (fstat(dfd, &sbuf) < 0) { 4025b1d7137Swdenk fprintf (stderr, "%s: Can't stat %s: %s\n", 4035b1d7137Swdenk cmdname, datafile, strerror(errno)); 4045b1d7137Swdenk exit (EXIT_FAILURE); 4055b1d7137Swdenk } 4065b1d7137Swdenk 407fa956fdeSMike Frysinger ptr = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, dfd, 0); 408fa956fdeSMike Frysinger if (ptr == MAP_FAILED) { 4095b1d7137Swdenk fprintf (stderr, "%s: Can't read %s: %s\n", 4105b1d7137Swdenk cmdname, datafile, strerror(errno)); 4115b1d7137Swdenk exit (EXIT_FAILURE); 4125b1d7137Swdenk } 4135b1d7137Swdenk 4145b1d7137Swdenk if (xflag) { 4155b1d7137Swdenk unsigned char *p = NULL; 4165b1d7137Swdenk /* 4175b1d7137Swdenk * XIP: do not append the image_header_t at the 4185b1d7137Swdenk * beginning of the file, but consume the space 4195b1d7137Swdenk * reserved for it. 4205b1d7137Swdenk */ 4215b1d7137Swdenk 422b97a2a0aSMarian Balakowicz if ((unsigned)sbuf.st_size < image_get_header_size ()) { 4235b1d7137Swdenk fprintf (stderr, 4245b1d7137Swdenk "%s: Bad size: \"%s\" is too small for XIP\n", 4255b1d7137Swdenk cmdname, datafile); 4265b1d7137Swdenk exit (EXIT_FAILURE); 4275b1d7137Swdenk } 4285b1d7137Swdenk 429b97a2a0aSMarian Balakowicz for (p = ptr; p < ptr + image_get_header_size (); p++) { 4305b1d7137Swdenk if ( *p != 0xff ) { 4315b1d7137Swdenk fprintf (stderr, 4325b1d7137Swdenk "%s: Bad file: \"%s\" has invalid buffer for XIP\n", 4335b1d7137Swdenk cmdname, datafile); 4345b1d7137Swdenk exit (EXIT_FAILURE); 4355b1d7137Swdenk } 4365b1d7137Swdenk } 4375b1d7137Swdenk 438b97a2a0aSMarian Balakowicz offset = image_get_header_size (); 4395b1d7137Swdenk } 4405b1d7137Swdenk 4415b1d7137Swdenk size = sbuf.st_size - offset; 4425b1d7137Swdenk if (write(ifd, ptr + offset, size) != size) { 4435b1d7137Swdenk fprintf (stderr, "%s: Write error on %s: %s\n", 4445b1d7137Swdenk cmdname, imagefile, strerror(errno)); 4455b1d7137Swdenk exit (EXIT_FAILURE); 4465b1d7137Swdenk } 4475b1d7137Swdenk 4485b1d7137Swdenk if (pad && ((tail = size % 4) != 0)) { 4495b1d7137Swdenk 4505b1d7137Swdenk if (write(ifd, (char *)&zero, 4-tail) != 4-tail) { 4515b1d7137Swdenk fprintf (stderr, "%s: Write error on %s: %s\n", 4525b1d7137Swdenk cmdname, imagefile, strerror(errno)); 4535b1d7137Swdenk exit (EXIT_FAILURE); 4545b1d7137Swdenk } 4555b1d7137Swdenk } 4565b1d7137Swdenk 4575b1d7137Swdenk (void) munmap((void *)ptr, sbuf.st_size); 4585b1d7137Swdenk (void) close (dfd); 4595b1d7137Swdenk } 4605b1d7137Swdenk 4615b1d7137Swdenk void 4625b1d7137Swdenk usage () 4635b1d7137Swdenk { 4645b1d7137Swdenk fprintf (stderr, "Usage: %s -l image\n" 4659d25438fSBartlomiej Sieka " -l ==> list image header information\n", 4669d25438fSBartlomiej Sieka cmdname); 4679d25438fSBartlomiej Sieka fprintf (stderr, " %s [-x] -A arch -O os -T type -C comp " 4689d25438fSBartlomiej Sieka "-a addr -e ep -n name -d data_file[:data_file...] image\n" 4699d25438fSBartlomiej Sieka " -A ==> set architecture to 'arch'\n" 4705b1d7137Swdenk " -O ==> set operating system to 'os'\n" 4715b1d7137Swdenk " -T ==> set image type to 'type'\n" 4725b1d7137Swdenk " -C ==> set compression type 'comp'\n" 4735b1d7137Swdenk " -a ==> set load address to 'addr' (hex)\n" 4745b1d7137Swdenk " -e ==> set entry point to 'ep' (hex)\n" 4755b1d7137Swdenk " -n ==> set image name to 'name'\n" 4765b1d7137Swdenk " -d ==> use image data from 'datafile'\n" 4779d25438fSBartlomiej Sieka " -x ==> set XIP (execute in place)\n", 4789d25438fSBartlomiej Sieka cmdname); 4799d25438fSBartlomiej Sieka fprintf (stderr, " %s [-D dtc_options] -f fit-image.its fit-image\n", 4809d25438fSBartlomiej Sieka cmdname); 4819d25438fSBartlomiej Sieka 4825b1d7137Swdenk exit (EXIT_FAILURE); 4835b1d7137Swdenk } 4849d25438fSBartlomiej Sieka 485f7644c0bSPrafulla Wadaskar static int 4869d25438fSBartlomiej Sieka image_verify_header (char *ptr, int image_size) 4879d25438fSBartlomiej Sieka { 4889d25438fSBartlomiej Sieka int len; 489*449609f5SPrafulla Wadaskar const unsigned char *data; 4909d25438fSBartlomiej Sieka uint32_t checksum; 4919d25438fSBartlomiej Sieka image_header_t header; 4929d25438fSBartlomiej Sieka image_header_t *hdr = &header; 4939d25438fSBartlomiej Sieka 4949d25438fSBartlomiej Sieka /* 4959d25438fSBartlomiej Sieka * create copy of header so that we can blank out the 4969d25438fSBartlomiej Sieka * checksum field for checking - this can't be done 4979d25438fSBartlomiej Sieka * on the PROT_READ mapped data. 4989d25438fSBartlomiej Sieka */ 4999d25438fSBartlomiej Sieka memcpy (hdr, ptr, sizeof(image_header_t)); 5009d25438fSBartlomiej Sieka 50137566090SMike Frysinger if (be32_to_cpu(hdr->ih_magic) != IH_MAGIC) { 5029d25438fSBartlomiej Sieka fprintf (stderr, 5039d25438fSBartlomiej Sieka "%s: Bad Magic Number: \"%s\" is no valid image\n", 5049d25438fSBartlomiej Sieka cmdname, imagefile); 505f7644c0bSPrafulla Wadaskar return -FDT_ERR_BADMAGIC; 5069d25438fSBartlomiej Sieka } 5079d25438fSBartlomiej Sieka 508*449609f5SPrafulla Wadaskar data = (const unsigned char *)hdr; 5099d25438fSBartlomiej Sieka len = sizeof(image_header_t); 5109d25438fSBartlomiej Sieka 51137566090SMike Frysinger checksum = be32_to_cpu(hdr->ih_hcrc); 51237566090SMike Frysinger hdr->ih_hcrc = cpu_to_be32(0); /* clear for re-calculation */ 5139d25438fSBartlomiej Sieka 5149d25438fSBartlomiej Sieka if (crc32 (0, data, len) != checksum) { 5159d25438fSBartlomiej Sieka fprintf (stderr, 5169d25438fSBartlomiej Sieka "%s: ERROR: \"%s\" has bad header checksum!\n", 5179d25438fSBartlomiej Sieka cmdname, imagefile); 518f7644c0bSPrafulla Wadaskar return -FDT_ERR_BADSTATE; 5199d25438fSBartlomiej Sieka } 5209d25438fSBartlomiej Sieka 521*449609f5SPrafulla Wadaskar data = (const unsigned char *)ptr + sizeof(image_header_t); 5229d25438fSBartlomiej Sieka len = image_size - sizeof(image_header_t) ; 5239d25438fSBartlomiej Sieka 52437566090SMike Frysinger if (crc32 (0, data, len) != be32_to_cpu(hdr->ih_dcrc)) { 5259d25438fSBartlomiej Sieka fprintf (stderr, 5269d25438fSBartlomiej Sieka "%s: ERROR: \"%s\" has corrupted data!\n", 5279d25438fSBartlomiej Sieka cmdname, imagefile); 528f7644c0bSPrafulla Wadaskar return -FDT_ERR_BADSTRUCTURE; 5299d25438fSBartlomiej Sieka } 530f7644c0bSPrafulla Wadaskar return 0; 5319d25438fSBartlomiej Sieka } 5329d25438fSBartlomiej Sieka 5339d25438fSBartlomiej Sieka /** 5349d25438fSBartlomiej Sieka * fit_handle_file - main FIT file processing function 5359d25438fSBartlomiej Sieka * 5369d25438fSBartlomiej Sieka * fit_handle_file() runs dtc to convert .its to .itb, includes 5379d25438fSBartlomiej Sieka * binary data, updates timestamp property and calculates hashes. 5389d25438fSBartlomiej Sieka * 5399d25438fSBartlomiej Sieka * datafile - .its file 5409d25438fSBartlomiej Sieka * imagefile - .itb file 5419d25438fSBartlomiej Sieka * 5429d25438fSBartlomiej Sieka * returns: 5439d25438fSBartlomiej Sieka * only on success, otherwise calls exit (EXIT_FAILURE); 5449d25438fSBartlomiej Sieka */ 5459d25438fSBartlomiej Sieka static void fit_handle_file (void) 5469d25438fSBartlomiej Sieka { 5479d25438fSBartlomiej Sieka char tmpfile[MKIMAGE_MAX_TMPFILE_LEN]; 5489d25438fSBartlomiej Sieka char cmd[MKIMAGE_MAX_DTC_CMDLINE_LEN]; 5499d25438fSBartlomiej Sieka int tfd; 5509d25438fSBartlomiej Sieka struct stat sbuf; 5519d25438fSBartlomiej Sieka unsigned char *ptr; 5529d25438fSBartlomiej Sieka 5539d25438fSBartlomiej Sieka /* call dtc to include binary properties into the tmp file */ 5549d25438fSBartlomiej Sieka if (strlen (imagefile) + strlen (MKIMAGE_TMPFILE_SUFFIX) + 1 > 5559d25438fSBartlomiej Sieka sizeof (tmpfile)) { 5569d25438fSBartlomiej Sieka fprintf (stderr, "%s: Image file name (%s) too long, " 5579d25438fSBartlomiej Sieka "can't create tmpfile", 5589d25438fSBartlomiej Sieka imagefile, cmdname); 5599d25438fSBartlomiej Sieka exit (EXIT_FAILURE); 5609d25438fSBartlomiej Sieka } 5619d25438fSBartlomiej Sieka sprintf (tmpfile, "%s%s", imagefile, MKIMAGE_TMPFILE_SUFFIX); 5629d25438fSBartlomiej Sieka 5639d25438fSBartlomiej Sieka /* dtc -I dts -O -p 200 datafile > tmpfile */ 5649d25438fSBartlomiej Sieka sprintf (cmd, "%s %s %s > %s", 5659d25438fSBartlomiej Sieka MKIMAGE_DTC, opt_dtc, datafile, tmpfile); 5669d25438fSBartlomiej Sieka debug ("Trying to execute \"%s\"\n", cmd); 5679d25438fSBartlomiej Sieka if (system (cmd) == -1) { 5689d25438fSBartlomiej Sieka fprintf (stderr, "%s: system(%s) failed: %s\n", 5699d25438fSBartlomiej Sieka cmdname, cmd, strerror(errno)); 5709d25438fSBartlomiej Sieka unlink (tmpfile); 5719d25438fSBartlomiej Sieka exit (EXIT_FAILURE); 5729d25438fSBartlomiej Sieka } 5739d25438fSBartlomiej Sieka 5749d25438fSBartlomiej Sieka /* load FIT blob into memory */ 5759d25438fSBartlomiej Sieka tfd = open (tmpfile, O_RDWR|O_BINARY); 5769d25438fSBartlomiej Sieka 5779d25438fSBartlomiej Sieka if (tfd < 0) { 5789d25438fSBartlomiej Sieka fprintf (stderr, "%s: Can't open %s: %s\n", 5799d25438fSBartlomiej Sieka cmdname, tmpfile, strerror(errno)); 5809d25438fSBartlomiej Sieka unlink (tmpfile); 5819d25438fSBartlomiej Sieka exit (EXIT_FAILURE); 5829d25438fSBartlomiej Sieka } 5839d25438fSBartlomiej Sieka 5849d25438fSBartlomiej Sieka if (fstat (tfd, &sbuf) < 0) { 5859d25438fSBartlomiej Sieka fprintf (stderr, "%s: Can't stat %s: %s\n", 5869d25438fSBartlomiej Sieka cmdname, tmpfile, strerror(errno)); 5879d25438fSBartlomiej Sieka unlink (tmpfile); 5889d25438fSBartlomiej Sieka exit (EXIT_FAILURE); 5899d25438fSBartlomiej Sieka } 5909d25438fSBartlomiej Sieka 591fa956fdeSMike Frysinger ptr = mmap (0, sbuf.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, tfd, 0); 592fa956fdeSMike Frysinger if (ptr == MAP_FAILED) { 5939d25438fSBartlomiej Sieka fprintf (stderr, "%s: Can't read %s: %s\n", 5949d25438fSBartlomiej Sieka cmdname, tmpfile, strerror(errno)); 5959d25438fSBartlomiej Sieka unlink (tmpfile); 5969d25438fSBartlomiej Sieka exit (EXIT_FAILURE); 5979d25438fSBartlomiej Sieka } 5989d25438fSBartlomiej Sieka 5999d25438fSBartlomiej Sieka /* check if ptr has a valid blob */ 6009d25438fSBartlomiej Sieka if (fdt_check_header (ptr)) { 6019d25438fSBartlomiej Sieka fprintf (stderr, "%s: Invalid FIT blob\n", cmdname); 6029d25438fSBartlomiej Sieka unlink (tmpfile); 6039d25438fSBartlomiej Sieka exit (EXIT_FAILURE); 6049d25438fSBartlomiej Sieka } 6059d25438fSBartlomiej Sieka 6069d25438fSBartlomiej Sieka /* set hashes for images in the blob */ 6079d25438fSBartlomiej Sieka if (fit_set_hashes (ptr)) { 6089d25438fSBartlomiej Sieka fprintf (stderr, "%s Can't add hashes to FIT blob", cmdname); 6099d25438fSBartlomiej Sieka unlink (tmpfile); 6109d25438fSBartlomiej Sieka exit (EXIT_FAILURE); 6119d25438fSBartlomiej Sieka } 6129d25438fSBartlomiej Sieka 6139d25438fSBartlomiej Sieka /* add a timestamp at offset 0 i.e., root */ 6149d25438fSBartlomiej Sieka if (fit_set_timestamp (ptr, 0, sbuf.st_mtime)) { 6159d25438fSBartlomiej Sieka fprintf (stderr, "%s: Can't add image timestamp\n", cmdname); 6169d25438fSBartlomiej Sieka unlink (tmpfile); 6179d25438fSBartlomiej Sieka exit (EXIT_FAILURE); 6189d25438fSBartlomiej Sieka } 6199d25438fSBartlomiej Sieka debug ("Added timestamp successfully\n"); 6209d25438fSBartlomiej Sieka 6219d25438fSBartlomiej Sieka munmap ((void *)ptr, sbuf.st_size); 6229d25438fSBartlomiej Sieka close (tfd); 6239d25438fSBartlomiej Sieka 6249d25438fSBartlomiej Sieka if (rename (tmpfile, imagefile) == -1) { 6259d25438fSBartlomiej Sieka fprintf (stderr, "%s: Can't rename %s to %s: %s\n", 6269d25438fSBartlomiej Sieka cmdname, tmpfile, imagefile, strerror (errno)); 6279d25438fSBartlomiej Sieka unlink (tmpfile); 6289d25438fSBartlomiej Sieka unlink (imagefile); 6299d25438fSBartlomiej Sieka exit (EXIT_FAILURE); 6309d25438fSBartlomiej Sieka } 6319d25438fSBartlomiej Sieka } 632