15b1d7137Swdenk /* 20c852a28Swdenk * (C) Copyright 2000-2004 35b1d7137Swdenk * DENX Software Engineering 45b1d7137Swdenk * Wolfgang Denk, wd@denx.de 55b1d7137Swdenk * All rights reserved. 60c852a28Swdenk * 70c852a28Swdenk * This program is free software; you can redistribute it and/or 80c852a28Swdenk * modify it under the terms of the GNU General Public License as 90c852a28Swdenk * published by the Free Software Foundation; either version 2 of 100c852a28Swdenk * the License, or (at your option) any later version. 110c852a28Swdenk * 120c852a28Swdenk * This program is distributed in the hope that it will be useful, 130c852a28Swdenk * but WITHOUT ANY WARRANTY; without even the implied warranty of 140c852a28Swdenk * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 150c852a28Swdenk * GNU General Public License for more details. 160c852a28Swdenk * 170c852a28Swdenk * You should have received a copy of the GNU General Public License 180c852a28Swdenk * along with this program; if not, write to the Free Software 190c852a28Swdenk * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 200c852a28Swdenk * MA 02111-1307 USA 215b1d7137Swdenk */ 225b1d7137Swdenk 23*b97a2a0aSMarian Balakowicz #include "mkimage.h" 245b1d7137Swdenk #include <image.h> 255b1d7137Swdenk 265b1d7137Swdenk extern int errno; 275b1d7137Swdenk 285b1d7137Swdenk #ifndef MAP_FAILED 295b1d7137Swdenk #define MAP_FAILED (-1) 305b1d7137Swdenk #endif 315b1d7137Swdenk 325b1d7137Swdenk char *cmdname; 335b1d7137Swdenk 345b1d7137Swdenk extern unsigned long crc32 (unsigned long crc, const char *buf, unsigned int len); 355b1d7137Swdenk 365b1d7137Swdenk typedef struct table_entry { 375b1d7137Swdenk int val; /* as defined in image.h */ 385b1d7137Swdenk char *sname; /* short (input) name */ 395b1d7137Swdenk char *lname; /* long (output) name */ 405b1d7137Swdenk } table_entry_t; 415b1d7137Swdenk 425b1d7137Swdenk table_entry_t arch_name[] = { 43*b97a2a0aSMarian Balakowicz { IH_ARCH_INVALID, NULL, "Invalid CPU", }, 44*b97a2a0aSMarian Balakowicz { IH_ARCH_ALPHA, "alpha", "Alpha", }, 45*b97a2a0aSMarian Balakowicz { IH_ARCH_ARM, "arm", "ARM", }, 46*b97a2a0aSMarian Balakowicz { IH_ARCH_I386, "x86", "Intel x86", }, 47*b97a2a0aSMarian Balakowicz { IH_ARCH_IA64, "ia64", "IA64", }, 48*b97a2a0aSMarian Balakowicz { IH_ARCH_M68K, "m68k", "MC68000", }, 49*b97a2a0aSMarian Balakowicz { IH_ARCH_MICROBLAZE, "microblaze", "MicroBlaze", }, 50*b97a2a0aSMarian Balakowicz { IH_ARCH_MIPS, "mips", "MIPS", }, 51*b97a2a0aSMarian Balakowicz { IH_ARCH_MIPS64, "mips64", "MIPS 64 Bit", }, 52*b97a2a0aSMarian Balakowicz { IH_ARCH_NIOS, "nios", "NIOS", }, 53*b97a2a0aSMarian Balakowicz { IH_ARCH_NIOS2, "nios2", "NIOS II", }, 54*b97a2a0aSMarian Balakowicz { IH_ARCH_PPC, "ppc", "PowerPC", }, 55*b97a2a0aSMarian Balakowicz { IH_ARCH_S390, "s390", "IBM S390", }, 56*b97a2a0aSMarian Balakowicz { IH_ARCH_SH, "sh", "SuperH", }, 57*b97a2a0aSMarian Balakowicz { IH_ARCH_SPARC, "sparc", "SPARC", }, 58*b97a2a0aSMarian Balakowicz { IH_ARCH_SPARC64, "sparc64", "SPARC 64 Bit", }, 59*b97a2a0aSMarian Balakowicz { IH_ARCH_BLACKFIN, "blackfin", "Blackfin", }, 60*b97a2a0aSMarian Balakowicz { IH_ARCH_AVR32, "avr32", "AVR32", }, 615b1d7137Swdenk { -1, "", "", }, 625b1d7137Swdenk }; 635b1d7137Swdenk 645b1d7137Swdenk table_entry_t os_name[] = { 655b1d7137Swdenk { IH_OS_INVALID, NULL, "Invalid OS", }, 665b1d7137Swdenk { IH_OS_4_4BSD, "4_4bsd", "4_4BSD", }, 67466b7410Swdenk { IH_OS_ARTOS, "artos", "ARTOS", }, 685b1d7137Swdenk { IH_OS_DELL, "dell", "Dell", }, 69466b7410Swdenk { IH_OS_ESIX, "esix", "Esix", }, 70466b7410Swdenk { IH_OS_FREEBSD, "freebsd", "FreeBSD", }, 71466b7410Swdenk { IH_OS_IRIX, "irix", "Irix", }, 72466b7410Swdenk { IH_OS_LINUX, "linux", "Linux", }, 735b1d7137Swdenk { IH_OS_LYNXOS, "lynxos", "LynxOS", }, 74466b7410Swdenk { IH_OS_NCR, "ncr", "NCR", }, 75466b7410Swdenk { IH_OS_NETBSD, "netbsd", "NetBSD", }, 76466b7410Swdenk { IH_OS_OPENBSD, "openbsd", "OpenBSD", }, 775b1d7137Swdenk { IH_OS_PSOS, "psos", "pSOS", }, 785b1d7137Swdenk { IH_OS_QNX, "qnx", "QNX", }, 79d791b1dcSwdenk { IH_OS_RTEMS, "rtems", "RTEMS", }, 80466b7410Swdenk { IH_OS_SCO, "sco", "SCO", }, 81466b7410Swdenk { IH_OS_SOLARIS, "solaris", "Solaris", }, 82466b7410Swdenk { IH_OS_SVR4, "svr4", "SVR4", }, 83466b7410Swdenk { IH_OS_U_BOOT, "u-boot", "U-Boot", }, 84466b7410Swdenk { IH_OS_VXWORKS, "vxworks", "VxWorks", }, 855b1d7137Swdenk { -1, "", "", }, 865b1d7137Swdenk }; 875b1d7137Swdenk 885b1d7137Swdenk table_entry_t type_name[] = { 895b1d7137Swdenk { IH_TYPE_INVALID, NULL, "Invalid Image", }, 90887b372fSwdenk { IH_TYPE_FILESYSTEM, "filesystem", "Filesystem Image", }, 91466b7410Swdenk { IH_TYPE_FIRMWARE, "firmware", "Firmware", }, 92466b7410Swdenk { IH_TYPE_KERNEL, "kernel", "Kernel Image", }, 93466b7410Swdenk { IH_TYPE_MULTI, "multi", "Multi-File Image", }, 94466b7410Swdenk { IH_TYPE_RAMDISK, "ramdisk", "RAMDisk Image", }, 95466b7410Swdenk { IH_TYPE_SCRIPT, "script", "Script", }, 96466b7410Swdenk { IH_TYPE_STANDALONE, "standalone", "Standalone Program", }, 9725c751e9SMatthew McClintock { IH_TYPE_FLATDT, "flat_dt", "Flat Device Tree", }, 985b1d7137Swdenk { -1, "", "", }, 995b1d7137Swdenk }; 1005b1d7137Swdenk 1015b1d7137Swdenk table_entry_t comp_name[] = { 1025b1d7137Swdenk { IH_COMP_NONE, "none", "uncompressed", }, 1035b1d7137Swdenk { IH_COMP_BZIP2, "bzip2", "bzip2 compressed", }, 104466b7410Swdenk { IH_COMP_GZIP, "gzip", "gzip compressed", }, 1055b1d7137Swdenk { -1, "", "", }, 1065b1d7137Swdenk }; 1075b1d7137Swdenk 1085b1d7137Swdenk static void copy_file (int, const char *, int); 1095b1d7137Swdenk static void usage (void); 1105b1d7137Swdenk static void print_header (image_header_t *); 1115b1d7137Swdenk static void print_type (image_header_t *); 1125b1d7137Swdenk static char *put_table_entry (table_entry_t *, char *, int); 1135b1d7137Swdenk static char *put_arch (int); 1145b1d7137Swdenk static char *put_type (int); 1155b1d7137Swdenk static char *put_os (int); 1165b1d7137Swdenk static char *put_comp (int); 1175b1d7137Swdenk static int get_table_entry (table_entry_t *, char *, char *); 1185b1d7137Swdenk static int get_arch(char *); 1195b1d7137Swdenk static int get_comp(char *); 1205b1d7137Swdenk static int get_os (char *); 1215b1d7137Swdenk static int get_type(char *); 1225b1d7137Swdenk 1235b1d7137Swdenk 1245b1d7137Swdenk char *datafile; 1255b1d7137Swdenk char *imagefile; 1265b1d7137Swdenk 1275b1d7137Swdenk int dflag = 0; 1285b1d7137Swdenk int eflag = 0; 1295b1d7137Swdenk int lflag = 0; 1305b1d7137Swdenk int vflag = 0; 1315b1d7137Swdenk int xflag = 0; 1325b1d7137Swdenk int opt_os = IH_OS_LINUX; 133*b97a2a0aSMarian Balakowicz int opt_arch = IH_ARCH_PPC; 1345b1d7137Swdenk int opt_type = IH_TYPE_KERNEL; 1355b1d7137Swdenk int opt_comp = IH_COMP_GZIP; 1365b1d7137Swdenk 1375b1d7137Swdenk image_header_t header; 1385b1d7137Swdenk image_header_t *hdr = &header; 1395b1d7137Swdenk 1405b1d7137Swdenk int 1415b1d7137Swdenk main (int argc, char **argv) 1425b1d7137Swdenk { 1435b1d7137Swdenk int ifd; 1445b1d7137Swdenk uint32_t checksum; 1455b1d7137Swdenk uint32_t addr; 1465b1d7137Swdenk uint32_t ep; 1475b1d7137Swdenk struct stat sbuf; 1485b1d7137Swdenk unsigned char *ptr; 1495b1d7137Swdenk char *name = ""; 1505b1d7137Swdenk 1515b1d7137Swdenk cmdname = *argv; 1525b1d7137Swdenk 1535b1d7137Swdenk addr = ep = 0; 1545b1d7137Swdenk 1555b1d7137Swdenk while (--argc > 0 && **++argv == '-') { 1565b1d7137Swdenk while (*++*argv) { 1575b1d7137Swdenk switch (**argv) { 1585b1d7137Swdenk case 'l': 1595b1d7137Swdenk lflag = 1; 1605b1d7137Swdenk break; 1615b1d7137Swdenk case 'A': 1625b1d7137Swdenk if ((--argc <= 0) || 1635b1d7137Swdenk (opt_arch = get_arch(*++argv)) < 0) 1645b1d7137Swdenk usage (); 1655b1d7137Swdenk goto NXTARG; 1665b1d7137Swdenk case 'C': 1675b1d7137Swdenk if ((--argc <= 0) || 1685b1d7137Swdenk (opt_comp = get_comp(*++argv)) < 0) 1695b1d7137Swdenk usage (); 1705b1d7137Swdenk goto NXTARG; 1715b1d7137Swdenk case 'O': 1725b1d7137Swdenk if ((--argc <= 0) || 1735b1d7137Swdenk (opt_os = get_os(*++argv)) < 0) 1745b1d7137Swdenk usage (); 1755b1d7137Swdenk goto NXTARG; 1765b1d7137Swdenk case 'T': 1775b1d7137Swdenk if ((--argc <= 0) || 1785b1d7137Swdenk (opt_type = get_type(*++argv)) < 0) 1795b1d7137Swdenk usage (); 1805b1d7137Swdenk goto NXTARG; 1815b1d7137Swdenk 1825b1d7137Swdenk case 'a': 1835b1d7137Swdenk if (--argc <= 0) 1845b1d7137Swdenk usage (); 1855b1d7137Swdenk addr = strtoul (*++argv, (char **)&ptr, 16); 1865b1d7137Swdenk if (*ptr) { 1875b1d7137Swdenk fprintf (stderr, 1885b1d7137Swdenk "%s: invalid load address %s\n", 1895b1d7137Swdenk cmdname, *argv); 1905b1d7137Swdenk exit (EXIT_FAILURE); 1915b1d7137Swdenk } 1925b1d7137Swdenk goto NXTARG; 1935b1d7137Swdenk case 'd': 1945b1d7137Swdenk if (--argc <= 0) 1955b1d7137Swdenk usage (); 1965b1d7137Swdenk datafile = *++argv; 1975b1d7137Swdenk dflag = 1; 1985b1d7137Swdenk goto NXTARG; 1995b1d7137Swdenk case 'e': 2005b1d7137Swdenk if (--argc <= 0) 2015b1d7137Swdenk usage (); 2025b1d7137Swdenk ep = strtoul (*++argv, (char **)&ptr, 16); 2035b1d7137Swdenk if (*ptr) { 2045b1d7137Swdenk fprintf (stderr, 2055b1d7137Swdenk "%s: invalid entry point %s\n", 2065b1d7137Swdenk cmdname, *argv); 2075b1d7137Swdenk exit (EXIT_FAILURE); 2085b1d7137Swdenk } 2095b1d7137Swdenk eflag = 1; 2105b1d7137Swdenk goto NXTARG; 2115b1d7137Swdenk case 'n': 2125b1d7137Swdenk if (--argc <= 0) 2135b1d7137Swdenk usage (); 2145b1d7137Swdenk name = *++argv; 2155b1d7137Swdenk goto NXTARG; 2165b1d7137Swdenk case 'v': 2175b1d7137Swdenk vflag++; 2185b1d7137Swdenk break; 2195b1d7137Swdenk case 'x': 2205b1d7137Swdenk xflag++; 2215b1d7137Swdenk break; 2225b1d7137Swdenk default: 2235b1d7137Swdenk usage (); 2245b1d7137Swdenk } 2255b1d7137Swdenk } 2265b1d7137Swdenk NXTARG: ; 2275b1d7137Swdenk } 2285b1d7137Swdenk 2295b1d7137Swdenk if ((argc != 1) || ((lflag ^ dflag) == 0)) 2305b1d7137Swdenk usage(); 2315b1d7137Swdenk 2325b1d7137Swdenk if (!eflag) { 2335b1d7137Swdenk ep = addr; 2345b1d7137Swdenk /* If XIP, entry point must be after the U-Boot header */ 2355b1d7137Swdenk if (xflag) 236*b97a2a0aSMarian Balakowicz ep += image_get_header_size (); 2375b1d7137Swdenk } 2385b1d7137Swdenk 2395b1d7137Swdenk /* 2405b1d7137Swdenk * If XIP, ensure the entry point is equal to the load address plus 2415b1d7137Swdenk * the size of the U-Boot header. 2425b1d7137Swdenk */ 2435b1d7137Swdenk if (xflag) { 244*b97a2a0aSMarian Balakowicz if (ep != addr + image_get_header_size ()) { 2453577d3a3SWolfgang Denk fprintf (stderr, 2463577d3a3SWolfgang Denk "%s: For XIP, the entry point must be the load addr + %lu\n", 247a6c7ad2fSwdenk cmdname, 248*b97a2a0aSMarian Balakowicz (unsigned long)image_get_header_size ()); 2495b1d7137Swdenk exit (EXIT_FAILURE); 2505b1d7137Swdenk } 2515b1d7137Swdenk } 2525b1d7137Swdenk 2535b1d7137Swdenk imagefile = *argv; 2545b1d7137Swdenk 2555b1d7137Swdenk if (lflag) { 256ef1464ccSwdenk ifd = open(imagefile, O_RDONLY|O_BINARY); 2575b1d7137Swdenk } else { 2585b1d7137Swdenk ifd = open(imagefile, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, 0666); 2595b1d7137Swdenk } 2605b1d7137Swdenk 2615b1d7137Swdenk if (ifd < 0) { 2625b1d7137Swdenk fprintf (stderr, "%s: Can't open %s: %s\n", 2635b1d7137Swdenk cmdname, imagefile, strerror(errno)); 2645b1d7137Swdenk exit (EXIT_FAILURE); 2655b1d7137Swdenk } 2665b1d7137Swdenk 2675b1d7137Swdenk if (lflag) { 2685b1d7137Swdenk int len; 2695b1d7137Swdenk char *data; 2705b1d7137Swdenk /* 2715b1d7137Swdenk * list header information of existing image 2725b1d7137Swdenk */ 2735b1d7137Swdenk if (fstat(ifd, &sbuf) < 0) { 2745b1d7137Swdenk fprintf (stderr, "%s: Can't stat %s: %s\n", 2755b1d7137Swdenk cmdname, imagefile, strerror(errno)); 2765b1d7137Swdenk exit (EXIT_FAILURE); 2775b1d7137Swdenk } 2785b1d7137Swdenk 279*b97a2a0aSMarian Balakowicz if ((unsigned)sbuf.st_size < image_get_header_size ()) { 2805b1d7137Swdenk fprintf (stderr, 2815b1d7137Swdenk "%s: Bad size: \"%s\" is no valid image\n", 2825b1d7137Swdenk cmdname, imagefile); 2835b1d7137Swdenk exit (EXIT_FAILURE); 2845b1d7137Swdenk } 2855b1d7137Swdenk 2865b1d7137Swdenk ptr = (unsigned char *)mmap(0, sbuf.st_size, 2875b1d7137Swdenk PROT_READ, MAP_SHARED, ifd, 0); 2885b1d7137Swdenk if ((caddr_t)ptr == (caddr_t)-1) { 2895b1d7137Swdenk fprintf (stderr, "%s: Can't read %s: %s\n", 2905b1d7137Swdenk cmdname, imagefile, strerror(errno)); 2915b1d7137Swdenk exit (EXIT_FAILURE); 2925b1d7137Swdenk } 2935b1d7137Swdenk 2945b1d7137Swdenk /* 295*b97a2a0aSMarian Balakowicz * image_check_hcrc() creates copy of header so that 296*b97a2a0aSMarian Balakowicz * we can blank out the checksum field for checking - 297*b97a2a0aSMarian Balakowicz * this can't be done on the PROT_READ mapped data. 2985b1d7137Swdenk */ 299*b97a2a0aSMarian Balakowicz hdr = (image_header_t *)ptr; 3005b1d7137Swdenk 301*b97a2a0aSMarian Balakowicz if (!image_check_magic (hdr)) { 3025b1d7137Swdenk fprintf (stderr, 3035b1d7137Swdenk "%s: Bad Magic Number: \"%s\" is no valid image\n", 3045b1d7137Swdenk cmdname, imagefile); 3055b1d7137Swdenk exit (EXIT_FAILURE); 3065b1d7137Swdenk } 3075b1d7137Swdenk 308*b97a2a0aSMarian Balakowicz if (!image_check_hcrc (hdr)) { 3095b1d7137Swdenk fprintf (stderr, 3103577d3a3SWolfgang Denk "%s: ERROR: \"%s\" has bad header checksum!\n", 3113577d3a3SWolfgang Denk cmdname, imagefile); 3123577d3a3SWolfgang Denk exit (EXIT_FAILURE); 3135b1d7137Swdenk } 3145b1d7137Swdenk 315*b97a2a0aSMarian Balakowicz data = (char *)image_get_data (hdr); 316*b97a2a0aSMarian Balakowicz len = sbuf.st_size - image_get_header_size (); 3175b1d7137Swdenk 318*b97a2a0aSMarian Balakowicz if (crc32(0, data, len) != image_get_dcrc (hdr)) { 3195b1d7137Swdenk fprintf (stderr, 3203577d3a3SWolfgang Denk "%s: ERROR: \"%s\" has corrupted data!\n", 3213577d3a3SWolfgang Denk cmdname, imagefile); 3223577d3a3SWolfgang Denk exit (EXIT_FAILURE); 3235b1d7137Swdenk } 3245b1d7137Swdenk 3255b1d7137Swdenk /* for multi-file images we need the data part, too */ 3265b1d7137Swdenk print_header ((image_header_t *)ptr); 3275b1d7137Swdenk 3285b1d7137Swdenk (void) munmap((void *)ptr, sbuf.st_size); 3295b1d7137Swdenk (void) close (ifd); 3305b1d7137Swdenk 3315b1d7137Swdenk exit (EXIT_SUCCESS); 3325b1d7137Swdenk } 3335b1d7137Swdenk 3345b1d7137Swdenk /* 3355b1d7137Swdenk * Must be -w then: 3365b1d7137Swdenk * 3375b1d7137Swdenk * write dummy header, to be fixed later 3385b1d7137Swdenk */ 339*b97a2a0aSMarian Balakowicz memset (hdr, 0, image_get_header_size ()); 3405b1d7137Swdenk 341*b97a2a0aSMarian Balakowicz if (write(ifd, hdr, image_get_header_size ()) != image_get_header_size ()) { 3425b1d7137Swdenk fprintf (stderr, "%s: Write error on %s: %s\n", 3435b1d7137Swdenk cmdname, imagefile, strerror(errno)); 3445b1d7137Swdenk exit (EXIT_FAILURE); 3455b1d7137Swdenk } 3465b1d7137Swdenk 3475b1d7137Swdenk if (opt_type == IH_TYPE_MULTI || opt_type == IH_TYPE_SCRIPT) { 3485b1d7137Swdenk char *file = datafile; 3493bb66806SWolfgang Denk uint32_t size; 3505b1d7137Swdenk 3515b1d7137Swdenk for (;;) { 3525b1d7137Swdenk char *sep = NULL; 3535b1d7137Swdenk 3545b1d7137Swdenk if (file) { 3555b1d7137Swdenk if ((sep = strchr(file, ':')) != NULL) { 3565b1d7137Swdenk *sep = '\0'; 3575b1d7137Swdenk } 3585b1d7137Swdenk 3595b1d7137Swdenk if (stat (file, &sbuf) < 0) { 3605b1d7137Swdenk fprintf (stderr, "%s: Can't stat %s: %s\n", 3615b1d7137Swdenk cmdname, file, strerror(errno)); 3625b1d7137Swdenk exit (EXIT_FAILURE); 3635b1d7137Swdenk } 364*b97a2a0aSMarian Balakowicz size = cpu_to_image (sbuf.st_size); 3655b1d7137Swdenk } else { 3665b1d7137Swdenk size = 0; 3675b1d7137Swdenk } 3685b1d7137Swdenk 3695b1d7137Swdenk if (write(ifd, (char *)&size, sizeof(size)) != sizeof(size)) { 3705b1d7137Swdenk fprintf (stderr, "%s: Write error on %s: %s\n", 3715b1d7137Swdenk cmdname, imagefile, strerror(errno)); 3725b1d7137Swdenk exit (EXIT_FAILURE); 3735b1d7137Swdenk } 3745b1d7137Swdenk 3755b1d7137Swdenk if (!file) { 3765b1d7137Swdenk break; 3775b1d7137Swdenk } 3785b1d7137Swdenk 3795b1d7137Swdenk if (sep) { 3805b1d7137Swdenk *sep = ':'; 3815b1d7137Swdenk file = sep + 1; 3825b1d7137Swdenk } else { 3835b1d7137Swdenk file = NULL; 3845b1d7137Swdenk } 3855b1d7137Swdenk } 3865b1d7137Swdenk 3875b1d7137Swdenk file = datafile; 3885b1d7137Swdenk 3895b1d7137Swdenk for (;;) { 3905b1d7137Swdenk char *sep = strchr(file, ':'); 3915b1d7137Swdenk if (sep) { 3925b1d7137Swdenk *sep = '\0'; 3935b1d7137Swdenk copy_file (ifd, file, 1); 3945b1d7137Swdenk *sep++ = ':'; 3955b1d7137Swdenk file = sep; 3965b1d7137Swdenk } else { 3975b1d7137Swdenk copy_file (ifd, file, 0); 3985b1d7137Swdenk break; 3995b1d7137Swdenk } 4005b1d7137Swdenk } 4015b1d7137Swdenk } else { 4025b1d7137Swdenk copy_file (ifd, datafile, 0); 4035b1d7137Swdenk } 4045b1d7137Swdenk 4055b1d7137Swdenk /* We're a bit of paranoid */ 4065dfaa50eSAubrey.Li #if defined(_POSIX_SYNCHRONIZED_IO) && !defined(__sun__) && !defined(__FreeBSD__) && !defined(__APPLE__) 4075b1d7137Swdenk (void) fdatasync (ifd); 4085b1d7137Swdenk #else 4095b1d7137Swdenk (void) fsync (ifd); 4105b1d7137Swdenk #endif 4115b1d7137Swdenk 4125b1d7137Swdenk if (fstat(ifd, &sbuf) < 0) { 4135b1d7137Swdenk fprintf (stderr, "%s: Can't stat %s: %s\n", 4145b1d7137Swdenk cmdname, imagefile, strerror(errno)); 4155b1d7137Swdenk exit (EXIT_FAILURE); 4165b1d7137Swdenk } 4175b1d7137Swdenk 4185b1d7137Swdenk ptr = (unsigned char *)mmap(0, sbuf.st_size, 4195b1d7137Swdenk PROT_READ|PROT_WRITE, MAP_SHARED, ifd, 0); 4205b1d7137Swdenk if (ptr == (unsigned char *)MAP_FAILED) { 4215b1d7137Swdenk fprintf (stderr, "%s: Can't map %s: %s\n", 4225b1d7137Swdenk cmdname, imagefile, strerror(errno)); 4235b1d7137Swdenk exit (EXIT_FAILURE); 4245b1d7137Swdenk } 4255b1d7137Swdenk 4265b1d7137Swdenk hdr = (image_header_t *)ptr; 4275b1d7137Swdenk 4285b1d7137Swdenk checksum = crc32 (0, 429*b97a2a0aSMarian Balakowicz (const char *)(ptr + image_get_header_size ()), 430*b97a2a0aSMarian Balakowicz sbuf.st_size - image_get_header_size () 4315b1d7137Swdenk ); 4325b1d7137Swdenk 4335b1d7137Swdenk /* Build new header */ 434*b97a2a0aSMarian Balakowicz image_set_magic (hdr, IH_MAGIC); 435*b97a2a0aSMarian Balakowicz image_set_time (hdr, sbuf.st_mtime); 436*b97a2a0aSMarian Balakowicz image_set_size (hdr, sbuf.st_size - image_get_header_size ()); 437*b97a2a0aSMarian Balakowicz image_set_load (hdr, addr); 438*b97a2a0aSMarian Balakowicz image_set_ep (hdr, ep); 439*b97a2a0aSMarian Balakowicz image_set_dcrc (hdr, checksum); 440*b97a2a0aSMarian Balakowicz image_set_os (hdr, opt_os); 441*b97a2a0aSMarian Balakowicz image_set_arch (hdr, opt_arch); 442*b97a2a0aSMarian Balakowicz image_set_type (hdr, opt_type); 443*b97a2a0aSMarian Balakowicz image_set_comp (hdr, opt_comp); 4445b1d7137Swdenk 445*b97a2a0aSMarian Balakowicz image_set_name (hdr, name); 4465b1d7137Swdenk 447*b97a2a0aSMarian Balakowicz checksum = crc32 (0, (const char *)hdr, image_get_header_size ()); 4485b1d7137Swdenk 449*b97a2a0aSMarian Balakowicz image_set_hcrc (hdr, checksum); 4505b1d7137Swdenk 4515b1d7137Swdenk print_header (hdr); 4525b1d7137Swdenk 4535b1d7137Swdenk (void) munmap((void *)ptr, sbuf.st_size); 4545b1d7137Swdenk 4555b1d7137Swdenk /* We're a bit of paranoid */ 4565dfaa50eSAubrey.Li #if defined(_POSIX_SYNCHRONIZED_IO) && !defined(__sun__) && !defined(__FreeBSD__) && !defined(__APPLE__) 4575b1d7137Swdenk (void) fdatasync (ifd); 4585b1d7137Swdenk #else 4595b1d7137Swdenk (void) fsync (ifd); 4605b1d7137Swdenk #endif 4615b1d7137Swdenk 4625b1d7137Swdenk if (close(ifd)) { 4635b1d7137Swdenk fprintf (stderr, "%s: Write error on %s: %s\n", 4645b1d7137Swdenk cmdname, imagefile, strerror(errno)); 4655b1d7137Swdenk exit (EXIT_FAILURE); 4665b1d7137Swdenk } 4675b1d7137Swdenk 4685b1d7137Swdenk exit (EXIT_SUCCESS); 4695b1d7137Swdenk } 4705b1d7137Swdenk 4715b1d7137Swdenk static void 4725b1d7137Swdenk copy_file (int ifd, const char *datafile, int pad) 4735b1d7137Swdenk { 4745b1d7137Swdenk int dfd; 4755b1d7137Swdenk struct stat sbuf; 4765b1d7137Swdenk unsigned char *ptr; 4775b1d7137Swdenk int tail; 4785b1d7137Swdenk int zero = 0; 4795b1d7137Swdenk int offset = 0; 4805b1d7137Swdenk int size; 4815b1d7137Swdenk 4825b1d7137Swdenk if (vflag) { 4835b1d7137Swdenk fprintf (stderr, "Adding Image %s\n", datafile); 4845b1d7137Swdenk } 4855b1d7137Swdenk 486ef1464ccSwdenk if ((dfd = open(datafile, O_RDONLY|O_BINARY)) < 0) { 4875b1d7137Swdenk fprintf (stderr, "%s: Can't open %s: %s\n", 4885b1d7137Swdenk cmdname, datafile, strerror(errno)); 4895b1d7137Swdenk exit (EXIT_FAILURE); 4905b1d7137Swdenk } 4915b1d7137Swdenk 4925b1d7137Swdenk if (fstat(dfd, &sbuf) < 0) { 4935b1d7137Swdenk fprintf (stderr, "%s: Can't stat %s: %s\n", 4945b1d7137Swdenk cmdname, datafile, strerror(errno)); 4955b1d7137Swdenk exit (EXIT_FAILURE); 4965b1d7137Swdenk } 4975b1d7137Swdenk 4985b1d7137Swdenk ptr = (unsigned char *)mmap(0, sbuf.st_size, 4995b1d7137Swdenk PROT_READ, MAP_SHARED, dfd, 0); 5005b1d7137Swdenk if (ptr == (unsigned char *)MAP_FAILED) { 5015b1d7137Swdenk fprintf (stderr, "%s: Can't read %s: %s\n", 5025b1d7137Swdenk cmdname, datafile, strerror(errno)); 5035b1d7137Swdenk exit (EXIT_FAILURE); 5045b1d7137Swdenk } 5055b1d7137Swdenk 5065b1d7137Swdenk if (xflag) { 5075b1d7137Swdenk unsigned char *p = NULL; 5085b1d7137Swdenk /* 5095b1d7137Swdenk * XIP: do not append the image_header_t at the 5105b1d7137Swdenk * beginning of the file, but consume the space 5115b1d7137Swdenk * reserved for it. 5125b1d7137Swdenk */ 5135b1d7137Swdenk 514*b97a2a0aSMarian Balakowicz if ((unsigned)sbuf.st_size < image_get_header_size ()) { 5155b1d7137Swdenk fprintf (stderr, 5165b1d7137Swdenk "%s: Bad size: \"%s\" is too small for XIP\n", 5175b1d7137Swdenk cmdname, datafile); 5185b1d7137Swdenk exit (EXIT_FAILURE); 5195b1d7137Swdenk } 5205b1d7137Swdenk 521*b97a2a0aSMarian Balakowicz for (p = ptr; p < ptr + image_get_header_size (); p++) { 5225b1d7137Swdenk if ( *p != 0xff ) { 5235b1d7137Swdenk fprintf (stderr, 5245b1d7137Swdenk "%s: Bad file: \"%s\" has invalid buffer for XIP\n", 5255b1d7137Swdenk cmdname, datafile); 5265b1d7137Swdenk exit (EXIT_FAILURE); 5275b1d7137Swdenk } 5285b1d7137Swdenk } 5295b1d7137Swdenk 530*b97a2a0aSMarian Balakowicz offset = image_get_header_size (); 5315b1d7137Swdenk } 5325b1d7137Swdenk 5335b1d7137Swdenk size = sbuf.st_size - offset; 5345b1d7137Swdenk if (write(ifd, ptr + offset, size) != size) { 5355b1d7137Swdenk fprintf (stderr, "%s: Write error on %s: %s\n", 5365b1d7137Swdenk cmdname, imagefile, strerror(errno)); 5375b1d7137Swdenk exit (EXIT_FAILURE); 5385b1d7137Swdenk } 5395b1d7137Swdenk 5405b1d7137Swdenk if (pad && ((tail = size % 4) != 0)) { 5415b1d7137Swdenk 5425b1d7137Swdenk if (write(ifd, (char *)&zero, 4-tail) != 4-tail) { 5435b1d7137Swdenk fprintf (stderr, "%s: Write error on %s: %s\n", 5445b1d7137Swdenk cmdname, imagefile, strerror(errno)); 5455b1d7137Swdenk exit (EXIT_FAILURE); 5465b1d7137Swdenk } 5475b1d7137Swdenk } 5485b1d7137Swdenk 5495b1d7137Swdenk (void) munmap((void *)ptr, sbuf.st_size); 5505b1d7137Swdenk (void) close (dfd); 5515b1d7137Swdenk } 5525b1d7137Swdenk 5535b1d7137Swdenk void 5545b1d7137Swdenk usage () 5555b1d7137Swdenk { 5565b1d7137Swdenk fprintf (stderr, "Usage: %s -l image\n" 5575b1d7137Swdenk " -l ==> list image header information\n" 5589d5028c2Swdenk " %s [-x] -A arch -O os -T type -C comp " 5595b1d7137Swdenk "-a addr -e ep -n name -d data_file[:data_file...] image\n", 5605b1d7137Swdenk cmdname, cmdname); 5615b1d7137Swdenk fprintf (stderr, " -A ==> set architecture to 'arch'\n" 5625b1d7137Swdenk " -O ==> set operating system to 'os'\n" 5635b1d7137Swdenk " -T ==> set image type to 'type'\n" 5645b1d7137Swdenk " -C ==> set compression type 'comp'\n" 5655b1d7137Swdenk " -a ==> set load address to 'addr' (hex)\n" 5665b1d7137Swdenk " -e ==> set entry point to 'ep' (hex)\n" 5675b1d7137Swdenk " -n ==> set image name to 'name'\n" 5685b1d7137Swdenk " -d ==> use image data from 'datafile'\n" 5695b1d7137Swdenk " -x ==> set XIP (execute in place)\n" 5705b1d7137Swdenk ); 5715b1d7137Swdenk exit (EXIT_FAILURE); 5725b1d7137Swdenk } 5735b1d7137Swdenk 5745b1d7137Swdenk static void 5755b1d7137Swdenk print_header (image_header_t *hdr) 5765b1d7137Swdenk { 5775b1d7137Swdenk time_t timestamp; 5785b1d7137Swdenk uint32_t size; 5795b1d7137Swdenk 580*b97a2a0aSMarian Balakowicz timestamp = (time_t)image_get_time (hdr); 581*b97a2a0aSMarian Balakowicz size = image_get_data_size (hdr); 5825b1d7137Swdenk 583*b97a2a0aSMarian Balakowicz printf ("Image Name: %.*s\n", IH_NMLEN, image_get_name (hdr)); 5845b1d7137Swdenk printf ("Created: %s", ctime(×tamp)); 5855b1d7137Swdenk printf ("Image Type: "); print_type(hdr); 5865b1d7137Swdenk printf ("Data Size: %d Bytes = %.2f kB = %.2f MB\n", 5875b1d7137Swdenk size, (double)size / 1.024e3, (double)size / 1.048576e6 ); 588*b97a2a0aSMarian Balakowicz printf ("Load Address: 0x%08X\n", image_get_load (hdr)); 589*b97a2a0aSMarian Balakowicz printf ("Entry Point: 0x%08X\n", image_get_ep (hdr)); 5905b1d7137Swdenk 591*b97a2a0aSMarian Balakowicz if (image_check_type (hdr, IH_TYPE_MULTI) || 592*b97a2a0aSMarian Balakowicz image_check_type (hdr, IH_TYPE_SCRIPT)) { 5935b1d7137Swdenk int i, ptrs; 5945b1d7137Swdenk uint32_t pos; 5950dab03baSWolfgang Denk uint32_t *len_ptr = (uint32_t *) ( 596*b97a2a0aSMarian Balakowicz (unsigned long)hdr + image_get_header_size () 5975b1d7137Swdenk ); 5985b1d7137Swdenk 5995b1d7137Swdenk /* determine number of images first (to calculate image offsets) */ 6005b1d7137Swdenk for (i=0; len_ptr[i]; ++i) /* null pointer terminates list */ 6015b1d7137Swdenk ; 6025b1d7137Swdenk ptrs = i; /* null pointer terminates list */ 6035b1d7137Swdenk 604*b97a2a0aSMarian Balakowicz pos = image_get_header_size () + ptrs * sizeof(long); 6055b1d7137Swdenk printf ("Contents:\n"); 6065b1d7137Swdenk for (i=0; len_ptr[i]; ++i) { 607*b97a2a0aSMarian Balakowicz size = image_to_cpu (len_ptr[i]); 6085b1d7137Swdenk 6095b1d7137Swdenk printf (" Image %d: %8d Bytes = %4d kB = %d MB\n", 6105b1d7137Swdenk i, size, size>>10, size>>20); 611*b97a2a0aSMarian Balakowicz if (image_check_type (hdr, IH_TYPE_SCRIPT) && i > 0) { 6125b1d7137Swdenk /* 6135b1d7137Swdenk * the user may need to know offsets 6145b1d7137Swdenk * if planning to do something with 6155b1d7137Swdenk * multiple files 6165b1d7137Swdenk */ 617bdccc4feSwdenk printf (" Offset = %08X\n", pos); 6185b1d7137Swdenk } 6195b1d7137Swdenk /* copy_file() will pad the first files to even word align */ 6205b1d7137Swdenk size += 3; 6215b1d7137Swdenk size &= ~3; 6225b1d7137Swdenk pos += size; 6235b1d7137Swdenk } 6245b1d7137Swdenk } 6255b1d7137Swdenk } 6265b1d7137Swdenk 6275b1d7137Swdenk 6285b1d7137Swdenk static void 6295b1d7137Swdenk print_type (image_header_t *hdr) 6305b1d7137Swdenk { 6315b1d7137Swdenk printf ("%s %s %s (%s)\n", 632*b97a2a0aSMarian Balakowicz put_arch (image_get_arch (hdr)), 633*b97a2a0aSMarian Balakowicz put_os (image_get_os (hdr)), 634*b97a2a0aSMarian Balakowicz put_type (image_get_type (hdr)), 635*b97a2a0aSMarian Balakowicz put_comp (image_get_comp (hdr)) 6365b1d7137Swdenk ); 6375b1d7137Swdenk } 6385b1d7137Swdenk 6395b1d7137Swdenk static char *put_arch (int arch) 6405b1d7137Swdenk { 6415b1d7137Swdenk return (put_table_entry(arch_name, "Unknown Architecture", arch)); 6425b1d7137Swdenk } 6435b1d7137Swdenk 6445b1d7137Swdenk static char *put_os (int os) 6455b1d7137Swdenk { 6465b1d7137Swdenk return (put_table_entry(os_name, "Unknown OS", os)); 6475b1d7137Swdenk } 6485b1d7137Swdenk 6495b1d7137Swdenk static char *put_type (int type) 6505b1d7137Swdenk { 6515b1d7137Swdenk return (put_table_entry(type_name, "Unknown Image", type)); 6525b1d7137Swdenk } 6535b1d7137Swdenk 6545b1d7137Swdenk static char *put_comp (int comp) 6555b1d7137Swdenk { 6565b1d7137Swdenk return (put_table_entry(comp_name, "Unknown Compression", comp)); 6575b1d7137Swdenk } 6585b1d7137Swdenk 6595b1d7137Swdenk static char *put_table_entry (table_entry_t *table, char *msg, int type) 6605b1d7137Swdenk { 6615b1d7137Swdenk for (; table->val>=0; ++table) { 6625b1d7137Swdenk if (table->val == type) 6635b1d7137Swdenk return (table->lname); 6645b1d7137Swdenk } 6655b1d7137Swdenk return (msg); 6665b1d7137Swdenk } 6675b1d7137Swdenk 6685b1d7137Swdenk static int get_arch(char *name) 6695b1d7137Swdenk { 6705b1d7137Swdenk return (get_table_entry(arch_name, "CPU", name)); 6715b1d7137Swdenk } 6725b1d7137Swdenk 6735b1d7137Swdenk 6745b1d7137Swdenk static int get_comp(char *name) 6755b1d7137Swdenk { 6765b1d7137Swdenk return (get_table_entry(comp_name, "Compression", name)); 6775b1d7137Swdenk } 6785b1d7137Swdenk 6795b1d7137Swdenk 6805b1d7137Swdenk static int get_os (char *name) 6815b1d7137Swdenk { 6825b1d7137Swdenk return (get_table_entry(os_name, "OS", name)); 6835b1d7137Swdenk } 6845b1d7137Swdenk 6855b1d7137Swdenk 6865b1d7137Swdenk static int get_type(char *name) 6875b1d7137Swdenk { 6885b1d7137Swdenk return (get_table_entry(type_name, "Image", name)); 6895b1d7137Swdenk } 6905b1d7137Swdenk 6915b1d7137Swdenk static int get_table_entry (table_entry_t *table, char *msg, char *name) 6925b1d7137Swdenk { 6935b1d7137Swdenk table_entry_t *t; 6945b1d7137Swdenk int first = 1; 6955b1d7137Swdenk 6965b1d7137Swdenk for (t=table; t->val>=0; ++t) { 6975b1d7137Swdenk if (t->sname && strcasecmp(t->sname, name)==0) 6985b1d7137Swdenk return (t->val); 6995b1d7137Swdenk } 7005b1d7137Swdenk fprintf (stderr, "\nInvalid %s Type - valid names are", msg); 7015b1d7137Swdenk for (t=table; t->val>=0; ++t) { 7025b1d7137Swdenk if (t->sname == NULL) 7035b1d7137Swdenk continue; 7045b1d7137Swdenk fprintf (stderr, "%c %s", (first) ? ':' : ',', t->sname); 7055b1d7137Swdenk first = 0; 7065b1d7137Swdenk } 7075b1d7137Swdenk fprintf (stderr, "\n"); 7085b1d7137Swdenk return (-1); 7095b1d7137Swdenk } 710