15b1d7137Swdenk /* 2*0c852a28Swdenk * (C) Copyright 2000-2004 35b1d7137Swdenk * DENX Software Engineering 45b1d7137Swdenk * Wolfgang Denk, wd@denx.de 55b1d7137Swdenk * All rights reserved. 6*0c852a28Swdenk * 7*0c852a28Swdenk * This program is free software; you can redistribute it and/or 8*0c852a28Swdenk * modify it under the terms of the GNU General Public License as 9*0c852a28Swdenk * published by the Free Software Foundation; either version 2 of 10*0c852a28Swdenk * the License, or (at your option) any later version. 11*0c852a28Swdenk * 12*0c852a28Swdenk * This program is distributed in the hope that it will be useful, 13*0c852a28Swdenk * but WITHOUT ANY WARRANTY; without even the implied warranty of 14*0c852a28Swdenk * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15*0c852a28Swdenk * GNU General Public License for more details. 16*0c852a28Swdenk * 17*0c852a28Swdenk * You should have received a copy of the GNU General Public License 18*0c852a28Swdenk * along with this program; if not, write to the Free Software 19*0c852a28Swdenk * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 20*0c852a28Swdenk * MA 02111-1307 USA 215b1d7137Swdenk */ 225b1d7137Swdenk 235b1d7137Swdenk #include <errno.h> 245b1d7137Swdenk #include <fcntl.h> 255b1d7137Swdenk #include <stdio.h> 265b1d7137Swdenk #include <stdlib.h> 275b1d7137Swdenk #include <string.h> 285b1d7137Swdenk #ifndef __WIN32__ 295b1d7137Swdenk #include <netinet/in.h> /* for host / network byte order conversions */ 305b1d7137Swdenk #endif 315b1d7137Swdenk #include <sys/mman.h> 325b1d7137Swdenk #include <sys/stat.h> 335b1d7137Swdenk #include <time.h> 345b1d7137Swdenk #include <unistd.h> 355b1d7137Swdenk 365b1d7137Swdenk #if defined(__BEOS__) || defined(__NetBSD__) || defined(__APPLE__) 375b1d7137Swdenk #include <inttypes.h> 385b1d7137Swdenk #endif 395b1d7137Swdenk 405b1d7137Swdenk #ifdef __WIN32__ 415b1d7137Swdenk typedef unsigned int __u32; 425b1d7137Swdenk 435b1d7137Swdenk #define SWAP_LONG(x) \ 445b1d7137Swdenk ((__u32)( \ 455b1d7137Swdenk (((__u32)(x) & (__u32)0x000000ffUL) << 24) | \ 465b1d7137Swdenk (((__u32)(x) & (__u32)0x0000ff00UL) << 8) | \ 475b1d7137Swdenk (((__u32)(x) & (__u32)0x00ff0000UL) >> 8) | \ 485b1d7137Swdenk (((__u32)(x) & (__u32)0xff000000UL) >> 24) )) 495b1d7137Swdenk typedef unsigned char uint8_t; 505b1d7137Swdenk typedef unsigned short uint16_t; 515b1d7137Swdenk typedef unsigned int uint32_t; 525b1d7137Swdenk 535b1d7137Swdenk #define ntohl(a) SWAP_LONG(a) 545b1d7137Swdenk #define htonl(a) SWAP_LONG(a) 555b1d7137Swdenk #endif /* __WIN32__ */ 565b1d7137Swdenk 57acf98e7fSwdenk #ifndef O_BINARY /* should be define'd on __WIN32__ */ 58acf98e7fSwdenk #define O_BINARY 0 59acf98e7fSwdenk #endif 60acf98e7fSwdenk 615b1d7137Swdenk #include <image.h> 625b1d7137Swdenk 635b1d7137Swdenk extern int errno; 645b1d7137Swdenk 655b1d7137Swdenk #ifndef MAP_FAILED 665b1d7137Swdenk #define MAP_FAILED (-1) 675b1d7137Swdenk #endif 685b1d7137Swdenk 695b1d7137Swdenk char *cmdname; 705b1d7137Swdenk 715b1d7137Swdenk extern unsigned long crc32 (unsigned long crc, const char *buf, unsigned int len); 725b1d7137Swdenk 735b1d7137Swdenk typedef struct table_entry { 745b1d7137Swdenk int val; /* as defined in image.h */ 755b1d7137Swdenk char *sname; /* short (input) name */ 765b1d7137Swdenk char *lname; /* long (output) name */ 775b1d7137Swdenk } table_entry_t; 785b1d7137Swdenk 795b1d7137Swdenk table_entry_t arch_name[] = { 805b1d7137Swdenk { IH_CPU_INVALID, NULL, "Invalid CPU", }, 815b1d7137Swdenk { IH_CPU_ALPHA, "alpha", "Alpha", }, 825b1d7137Swdenk { IH_CPU_ARM, "arm", "ARM", }, 835b1d7137Swdenk { IH_CPU_I386, "x86", "Intel x86", }, 845b1d7137Swdenk { IH_CPU_IA64, "ia64", "IA64", }, 855b1d7137Swdenk { IH_CPU_MIPS, "mips", "MIPS", }, 865b1d7137Swdenk { IH_CPU_MIPS64, "mips64", "MIPS 64 Bit", }, 875b1d7137Swdenk { IH_CPU_PPC, "ppc", "PowerPC", }, 885b1d7137Swdenk { IH_CPU_S390, "s390", "IBM S390", }, 895b1d7137Swdenk { IH_CPU_SH, "sh", "SuperH", }, 905b1d7137Swdenk { IH_CPU_SPARC, "sparc", "SPARC", }, 915b1d7137Swdenk { IH_CPU_SPARC64, "sparc64", "SPARC 64 Bit", }, 928564acf9Swdenk { IH_CPU_M68K, "m68k", "MC68000", }, 935b1d7137Swdenk { -1, "", "", }, 945b1d7137Swdenk }; 955b1d7137Swdenk 965b1d7137Swdenk table_entry_t os_name[] = { 975b1d7137Swdenk { IH_OS_INVALID, NULL, "Invalid OS", }, 985b1d7137Swdenk { IH_OS_OPENBSD, "openbsd", "OpenBSD", }, 995b1d7137Swdenk { IH_OS_NETBSD, "netbsd", "NetBSD", }, 1005b1d7137Swdenk { IH_OS_FREEBSD, "freebsd", "FreeBSD", }, 1015b1d7137Swdenk { IH_OS_4_4BSD, "4_4bsd", "4_4BSD", }, 1025b1d7137Swdenk { IH_OS_LINUX, "linux", "Linux", }, 1035b1d7137Swdenk { IH_OS_SVR4, "svr4", "SVR4", }, 1045b1d7137Swdenk { IH_OS_ESIX, "esix", "Esix", }, 1055b1d7137Swdenk { IH_OS_SOLARIS, "solaris", "Solaris", }, 1065b1d7137Swdenk { IH_OS_IRIX, "irix", "Irix", }, 1075b1d7137Swdenk { IH_OS_SCO, "sco", "SCO", }, 1085b1d7137Swdenk { IH_OS_DELL, "dell", "Dell", }, 1095b1d7137Swdenk { IH_OS_NCR, "ncr", "NCR", }, 1105b1d7137Swdenk { IH_OS_LYNXOS, "lynxos", "LynxOS", }, 1115b1d7137Swdenk { IH_OS_VXWORKS, "vxworks", "VxWorks", }, 1125b1d7137Swdenk { IH_OS_PSOS, "psos", "pSOS", }, 1135b1d7137Swdenk { IH_OS_QNX, "qnx", "QNX", }, 1145b1d7137Swdenk { IH_OS_U_BOOT, "u-boot", "U-Boot", }, 115d791b1dcSwdenk { IH_OS_RTEMS, "rtems", "RTEMS", }, 1167f70e853Swdenk { IH_OS_ARTOS, "artos", "ARTOS", }, 1175b1d7137Swdenk { -1, "", "", }, 1185b1d7137Swdenk }; 1195b1d7137Swdenk 1205b1d7137Swdenk table_entry_t type_name[] = { 1215b1d7137Swdenk { IH_TYPE_INVALID, NULL, "Invalid Image", }, 1225b1d7137Swdenk { IH_TYPE_STANDALONE, "standalone", "Standalone Program", }, 1235b1d7137Swdenk { IH_TYPE_KERNEL, "kernel", "Kernel Image", }, 1245b1d7137Swdenk { IH_TYPE_RAMDISK, "ramdisk", "RAMDisk Image", }, 1255b1d7137Swdenk { IH_TYPE_MULTI, "multi", "Multi-File Image", }, 1265b1d7137Swdenk { IH_TYPE_FIRMWARE, "firmware", "Firmware", }, 1275b1d7137Swdenk { IH_TYPE_SCRIPT, "script", "Script", }, 128887b372fSwdenk { IH_TYPE_FILESYSTEM, "filesystem", "Filesystem Image", }, 1295b1d7137Swdenk { -1, "", "", }, 1305b1d7137Swdenk }; 1315b1d7137Swdenk 1325b1d7137Swdenk table_entry_t comp_name[] = { 1335b1d7137Swdenk { IH_COMP_NONE, "none", "uncompressed", }, 1345b1d7137Swdenk { IH_COMP_GZIP, "gzip", "gzip compressed", }, 1355b1d7137Swdenk { IH_COMP_BZIP2, "bzip2", "bzip2 compressed", }, 1365b1d7137Swdenk { -1, "", "", }, 1375b1d7137Swdenk }; 1385b1d7137Swdenk 1395b1d7137Swdenk static void copy_file (int, const char *, int); 1405b1d7137Swdenk static void usage (void); 1415b1d7137Swdenk static void print_header (image_header_t *); 1425b1d7137Swdenk static void print_type (image_header_t *); 1435b1d7137Swdenk static char *put_table_entry (table_entry_t *, char *, int); 1445b1d7137Swdenk static char *put_arch (int); 1455b1d7137Swdenk static char *put_type (int); 1465b1d7137Swdenk static char *put_os (int); 1475b1d7137Swdenk static char *put_comp (int); 1485b1d7137Swdenk static int get_table_entry (table_entry_t *, char *, char *); 1495b1d7137Swdenk static int get_arch(char *); 1505b1d7137Swdenk static int get_comp(char *); 1515b1d7137Swdenk static int get_os (char *); 1525b1d7137Swdenk static int get_type(char *); 1535b1d7137Swdenk 1545b1d7137Swdenk 1555b1d7137Swdenk char *datafile; 1565b1d7137Swdenk char *imagefile; 1575b1d7137Swdenk 1585b1d7137Swdenk int dflag = 0; 1595b1d7137Swdenk int eflag = 0; 1605b1d7137Swdenk int lflag = 0; 1615b1d7137Swdenk int vflag = 0; 1625b1d7137Swdenk int xflag = 0; 1635b1d7137Swdenk int opt_os = IH_OS_LINUX; 1645b1d7137Swdenk int opt_arch = IH_CPU_PPC; 1655b1d7137Swdenk int opt_type = IH_TYPE_KERNEL; 1665b1d7137Swdenk int opt_comp = IH_COMP_GZIP; 1675b1d7137Swdenk 1685b1d7137Swdenk image_header_t header; 1695b1d7137Swdenk image_header_t *hdr = &header; 1705b1d7137Swdenk 1715b1d7137Swdenk int 1725b1d7137Swdenk main (int argc, char **argv) 1735b1d7137Swdenk { 1745b1d7137Swdenk int ifd; 1755b1d7137Swdenk uint32_t checksum; 1765b1d7137Swdenk uint32_t addr; 1775b1d7137Swdenk uint32_t ep; 1785b1d7137Swdenk struct stat sbuf; 1795b1d7137Swdenk unsigned char *ptr; 1805b1d7137Swdenk char *name = ""; 1815b1d7137Swdenk 1825b1d7137Swdenk cmdname = *argv; 1835b1d7137Swdenk 1845b1d7137Swdenk addr = ep = 0; 1855b1d7137Swdenk 1865b1d7137Swdenk while (--argc > 0 && **++argv == '-') { 1875b1d7137Swdenk while (*++*argv) { 1885b1d7137Swdenk switch (**argv) { 1895b1d7137Swdenk case 'l': 1905b1d7137Swdenk lflag = 1; 1915b1d7137Swdenk break; 1925b1d7137Swdenk case 'A': 1935b1d7137Swdenk if ((--argc <= 0) || 1945b1d7137Swdenk (opt_arch = get_arch(*++argv)) < 0) 1955b1d7137Swdenk usage (); 1965b1d7137Swdenk goto NXTARG; 1975b1d7137Swdenk case 'C': 1985b1d7137Swdenk if ((--argc <= 0) || 1995b1d7137Swdenk (opt_comp = get_comp(*++argv)) < 0) 2005b1d7137Swdenk usage (); 2015b1d7137Swdenk goto NXTARG; 2025b1d7137Swdenk case 'O': 2035b1d7137Swdenk if ((--argc <= 0) || 2045b1d7137Swdenk (opt_os = get_os(*++argv)) < 0) 2055b1d7137Swdenk usage (); 2065b1d7137Swdenk goto NXTARG; 2075b1d7137Swdenk case 'T': 2085b1d7137Swdenk if ((--argc <= 0) || 2095b1d7137Swdenk (opt_type = get_type(*++argv)) < 0) 2105b1d7137Swdenk usage (); 2115b1d7137Swdenk goto NXTARG; 2125b1d7137Swdenk 2135b1d7137Swdenk case 'a': 2145b1d7137Swdenk if (--argc <= 0) 2155b1d7137Swdenk usage (); 2165b1d7137Swdenk addr = strtoul (*++argv, (char **)&ptr, 16); 2175b1d7137Swdenk if (*ptr) { 2185b1d7137Swdenk fprintf (stderr, 2195b1d7137Swdenk "%s: invalid load address %s\n", 2205b1d7137Swdenk cmdname, *argv); 2215b1d7137Swdenk exit (EXIT_FAILURE); 2225b1d7137Swdenk } 2235b1d7137Swdenk goto NXTARG; 2245b1d7137Swdenk case 'd': 2255b1d7137Swdenk if (--argc <= 0) 2265b1d7137Swdenk usage (); 2275b1d7137Swdenk datafile = *++argv; 2285b1d7137Swdenk dflag = 1; 2295b1d7137Swdenk goto NXTARG; 2305b1d7137Swdenk case 'e': 2315b1d7137Swdenk if (--argc <= 0) 2325b1d7137Swdenk usage (); 2335b1d7137Swdenk ep = strtoul (*++argv, (char **)&ptr, 16); 2345b1d7137Swdenk if (*ptr) { 2355b1d7137Swdenk fprintf (stderr, 2365b1d7137Swdenk "%s: invalid entry point %s\n", 2375b1d7137Swdenk cmdname, *argv); 2385b1d7137Swdenk exit (EXIT_FAILURE); 2395b1d7137Swdenk } 2405b1d7137Swdenk eflag = 1; 2415b1d7137Swdenk goto NXTARG; 2425b1d7137Swdenk case 'n': 2435b1d7137Swdenk if (--argc <= 0) 2445b1d7137Swdenk usage (); 2455b1d7137Swdenk name = *++argv; 2465b1d7137Swdenk goto NXTARG; 2475b1d7137Swdenk case 'v': 2485b1d7137Swdenk vflag++; 2495b1d7137Swdenk break; 2505b1d7137Swdenk case 'x': 2515b1d7137Swdenk xflag++; 2525b1d7137Swdenk break; 2535b1d7137Swdenk default: 2545b1d7137Swdenk usage (); 2555b1d7137Swdenk } 2565b1d7137Swdenk } 2575b1d7137Swdenk NXTARG: ; 2585b1d7137Swdenk } 2595b1d7137Swdenk 2605b1d7137Swdenk if ((argc != 1) || ((lflag ^ dflag) == 0)) 2615b1d7137Swdenk usage(); 2625b1d7137Swdenk 2635b1d7137Swdenk if (!eflag) { 2645b1d7137Swdenk ep = addr; 2655b1d7137Swdenk /* If XIP, entry point must be after the U-Boot header */ 2665b1d7137Swdenk if (xflag) 2675b1d7137Swdenk ep += sizeof(image_header_t); 2685b1d7137Swdenk } 2695b1d7137Swdenk 2705b1d7137Swdenk /* 2715b1d7137Swdenk * If XIP, ensure the entry point is equal to the load address plus 2725b1d7137Swdenk * the size of the U-Boot header. 2735b1d7137Swdenk */ 2745b1d7137Swdenk if (xflag) { 2755b1d7137Swdenk if (ep != addr + sizeof(image_header_t)) { 276a6c7ad2fSwdenk fprintf (stderr, "%s: For XIP, the entry point must be the load addr + %lu\n", 277a6c7ad2fSwdenk cmdname, 278a6c7ad2fSwdenk (unsigned long)sizeof(image_header_t)); 2795b1d7137Swdenk exit (EXIT_FAILURE); 2805b1d7137Swdenk } 2815b1d7137Swdenk } 2825b1d7137Swdenk 2835b1d7137Swdenk imagefile = *argv; 2845b1d7137Swdenk 2855b1d7137Swdenk if (lflag) { 286ef1464ccSwdenk ifd = open(imagefile, O_RDONLY|O_BINARY); 2875b1d7137Swdenk } else { 2885b1d7137Swdenk ifd = open(imagefile, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, 0666); 2895b1d7137Swdenk } 2905b1d7137Swdenk 2915b1d7137Swdenk if (ifd < 0) { 2925b1d7137Swdenk fprintf (stderr, "%s: Can't open %s: %s\n", 2935b1d7137Swdenk cmdname, imagefile, strerror(errno)); 2945b1d7137Swdenk exit (EXIT_FAILURE); 2955b1d7137Swdenk } 2965b1d7137Swdenk 2975b1d7137Swdenk if (lflag) { 2985b1d7137Swdenk int len; 2995b1d7137Swdenk char *data; 3005b1d7137Swdenk /* 3015b1d7137Swdenk * list header information of existing image 3025b1d7137Swdenk */ 3035b1d7137Swdenk if (fstat(ifd, &sbuf) < 0) { 3045b1d7137Swdenk fprintf (stderr, "%s: Can't stat %s: %s\n", 3055b1d7137Swdenk cmdname, imagefile, strerror(errno)); 3065b1d7137Swdenk exit (EXIT_FAILURE); 3075b1d7137Swdenk } 3085b1d7137Swdenk 3095bb226e8Swdenk if ((unsigned)sbuf.st_size < sizeof(image_header_t)) { 3105b1d7137Swdenk fprintf (stderr, 3115b1d7137Swdenk "%s: Bad size: \"%s\" is no valid image\n", 3125b1d7137Swdenk cmdname, imagefile); 3135b1d7137Swdenk exit (EXIT_FAILURE); 3145b1d7137Swdenk } 3155b1d7137Swdenk 3165b1d7137Swdenk ptr = (unsigned char *)mmap(0, sbuf.st_size, 3175b1d7137Swdenk PROT_READ, MAP_SHARED, ifd, 0); 3185b1d7137Swdenk if ((caddr_t)ptr == (caddr_t)-1) { 3195b1d7137Swdenk fprintf (stderr, "%s: Can't read %s: %s\n", 3205b1d7137Swdenk cmdname, imagefile, strerror(errno)); 3215b1d7137Swdenk exit (EXIT_FAILURE); 3225b1d7137Swdenk } 3235b1d7137Swdenk 3245b1d7137Swdenk /* 3255b1d7137Swdenk * create copy of header so that we can blank out the 3265b1d7137Swdenk * checksum field for checking - this can't be done 3275b1d7137Swdenk * on the PROT_READ mapped data. 3285b1d7137Swdenk */ 3295b1d7137Swdenk memcpy (hdr, ptr, sizeof(image_header_t)); 3305b1d7137Swdenk 3315b1d7137Swdenk if (ntohl(hdr->ih_magic) != IH_MAGIC) { 3325b1d7137Swdenk fprintf (stderr, 3335b1d7137Swdenk "%s: Bad Magic Number: \"%s\" is no valid image\n", 3345b1d7137Swdenk cmdname, imagefile); 3355b1d7137Swdenk exit (EXIT_FAILURE); 3365b1d7137Swdenk } 3375b1d7137Swdenk 3385b1d7137Swdenk data = (char *)hdr; 3395b1d7137Swdenk len = sizeof(image_header_t); 3405b1d7137Swdenk 3415b1d7137Swdenk checksum = ntohl(hdr->ih_hcrc); 3425b1d7137Swdenk hdr->ih_hcrc = htonl(0); /* clear for re-calculation */ 3435b1d7137Swdenk 3445b1d7137Swdenk if (crc32 (0, data, len) != checksum) { 3455b1d7137Swdenk fprintf (stderr, 3465b1d7137Swdenk "*** Warning: \"%s\" has bad header checksum!\n", 3475b1d7137Swdenk imagefile); 3485b1d7137Swdenk } 3495b1d7137Swdenk 3505b1d7137Swdenk data = (char *)(ptr + sizeof(image_header_t)); 3515b1d7137Swdenk len = sbuf.st_size - sizeof(image_header_t) ; 3525b1d7137Swdenk 3535b1d7137Swdenk if (crc32 (0, data, len) != ntohl(hdr->ih_dcrc)) { 3545b1d7137Swdenk fprintf (stderr, 3555b1d7137Swdenk "*** Warning: \"%s\" has corrupted data!\n", 3565b1d7137Swdenk imagefile); 3575b1d7137Swdenk } 3585b1d7137Swdenk 3595b1d7137Swdenk /* for multi-file images we need the data part, too */ 3605b1d7137Swdenk print_header ((image_header_t *)ptr); 3615b1d7137Swdenk 3625b1d7137Swdenk (void) munmap((void *)ptr, sbuf.st_size); 3635b1d7137Swdenk (void) close (ifd); 3645b1d7137Swdenk 3655b1d7137Swdenk exit (EXIT_SUCCESS); 3665b1d7137Swdenk } 3675b1d7137Swdenk 3685b1d7137Swdenk /* 3695b1d7137Swdenk * Must be -w then: 3705b1d7137Swdenk * 3715b1d7137Swdenk * write dummy header, to be fixed later 3725b1d7137Swdenk */ 3735b1d7137Swdenk memset (hdr, 0, sizeof(image_header_t)); 3745b1d7137Swdenk 3755b1d7137Swdenk if (write(ifd, hdr, sizeof(image_header_t)) != sizeof(image_header_t)) { 3765b1d7137Swdenk fprintf (stderr, "%s: Write error on %s: %s\n", 3775b1d7137Swdenk cmdname, imagefile, strerror(errno)); 3785b1d7137Swdenk exit (EXIT_FAILURE); 3795b1d7137Swdenk } 3805b1d7137Swdenk 3815b1d7137Swdenk if (opt_type == IH_TYPE_MULTI || opt_type == IH_TYPE_SCRIPT) { 3825b1d7137Swdenk char *file = datafile; 3835b1d7137Swdenk unsigned long size; 3845b1d7137Swdenk 3855b1d7137Swdenk for (;;) { 3865b1d7137Swdenk char *sep = NULL; 3875b1d7137Swdenk 3885b1d7137Swdenk if (file) { 3895b1d7137Swdenk if ((sep = strchr(file, ':')) != NULL) { 3905b1d7137Swdenk *sep = '\0'; 3915b1d7137Swdenk } 3925b1d7137Swdenk 3935b1d7137Swdenk if (stat (file, &sbuf) < 0) { 3945b1d7137Swdenk fprintf (stderr, "%s: Can't stat %s: %s\n", 3955b1d7137Swdenk cmdname, file, strerror(errno)); 3965b1d7137Swdenk exit (EXIT_FAILURE); 3975b1d7137Swdenk } 3985b1d7137Swdenk size = htonl(sbuf.st_size); 3995b1d7137Swdenk } else { 4005b1d7137Swdenk size = 0; 4015b1d7137Swdenk } 4025b1d7137Swdenk 4035b1d7137Swdenk if (write(ifd, (char *)&size, sizeof(size)) != sizeof(size)) { 4045b1d7137Swdenk fprintf (stderr, "%s: Write error on %s: %s\n", 4055b1d7137Swdenk cmdname, imagefile, strerror(errno)); 4065b1d7137Swdenk exit (EXIT_FAILURE); 4075b1d7137Swdenk } 4085b1d7137Swdenk 4095b1d7137Swdenk if (!file) { 4105b1d7137Swdenk break; 4115b1d7137Swdenk } 4125b1d7137Swdenk 4135b1d7137Swdenk if (sep) { 4145b1d7137Swdenk *sep = ':'; 4155b1d7137Swdenk file = sep + 1; 4165b1d7137Swdenk } else { 4175b1d7137Swdenk file = NULL; 4185b1d7137Swdenk } 4195b1d7137Swdenk } 4205b1d7137Swdenk 4215b1d7137Swdenk file = datafile; 4225b1d7137Swdenk 4235b1d7137Swdenk for (;;) { 4245b1d7137Swdenk char *sep = strchr(file, ':'); 4255b1d7137Swdenk if (sep) { 4265b1d7137Swdenk *sep = '\0'; 4275b1d7137Swdenk copy_file (ifd, file, 1); 4285b1d7137Swdenk *sep++ = ':'; 4295b1d7137Swdenk file = sep; 4305b1d7137Swdenk } else { 4315b1d7137Swdenk copy_file (ifd, file, 0); 4325b1d7137Swdenk break; 4335b1d7137Swdenk } 4345b1d7137Swdenk } 4355b1d7137Swdenk } else { 4365b1d7137Swdenk copy_file (ifd, datafile, 0); 4375b1d7137Swdenk } 4385b1d7137Swdenk 4395b1d7137Swdenk /* We're a bit of paranoid */ 440147031aeSwdenk #if defined(_POSIX_SYNCHRONIZED_IO) && !defined(__sun__) && !defined(__FreeBSD__) 4415b1d7137Swdenk (void) fdatasync (ifd); 4425b1d7137Swdenk #else 4435b1d7137Swdenk (void) fsync (ifd); 4445b1d7137Swdenk #endif 4455b1d7137Swdenk 4465b1d7137Swdenk if (fstat(ifd, &sbuf) < 0) { 4475b1d7137Swdenk fprintf (stderr, "%s: Can't stat %s: %s\n", 4485b1d7137Swdenk cmdname, imagefile, strerror(errno)); 4495b1d7137Swdenk exit (EXIT_FAILURE); 4505b1d7137Swdenk } 4515b1d7137Swdenk 4525b1d7137Swdenk ptr = (unsigned char *)mmap(0, sbuf.st_size, 4535b1d7137Swdenk PROT_READ|PROT_WRITE, MAP_SHARED, ifd, 0); 4545b1d7137Swdenk if (ptr == (unsigned char *)MAP_FAILED) { 4555b1d7137Swdenk fprintf (stderr, "%s: Can't map %s: %s\n", 4565b1d7137Swdenk cmdname, imagefile, strerror(errno)); 4575b1d7137Swdenk exit (EXIT_FAILURE); 4585b1d7137Swdenk } 4595b1d7137Swdenk 4605b1d7137Swdenk hdr = (image_header_t *)ptr; 4615b1d7137Swdenk 4625b1d7137Swdenk checksum = crc32 (0, 4635b1d7137Swdenk (const char *)(ptr + sizeof(image_header_t)), 4645b1d7137Swdenk sbuf.st_size - sizeof(image_header_t) 4655b1d7137Swdenk ); 4665b1d7137Swdenk 4675b1d7137Swdenk /* Build new header */ 4685b1d7137Swdenk hdr->ih_magic = htonl(IH_MAGIC); 4695b1d7137Swdenk hdr->ih_time = htonl(sbuf.st_mtime); 4705b1d7137Swdenk hdr->ih_size = htonl(sbuf.st_size - sizeof(image_header_t)); 4715b1d7137Swdenk hdr->ih_load = htonl(addr); 4725b1d7137Swdenk hdr->ih_ep = htonl(ep); 4735b1d7137Swdenk hdr->ih_dcrc = htonl(checksum); 4745b1d7137Swdenk hdr->ih_os = opt_os; 4755b1d7137Swdenk hdr->ih_arch = opt_arch; 4765b1d7137Swdenk hdr->ih_type = opt_type; 4775b1d7137Swdenk hdr->ih_comp = opt_comp; 4785b1d7137Swdenk 4795b1d7137Swdenk strncpy((char *)hdr->ih_name, name, IH_NMLEN); 4805b1d7137Swdenk 4815b1d7137Swdenk checksum = crc32(0,(const char *)hdr,sizeof(image_header_t)); 4825b1d7137Swdenk 4835b1d7137Swdenk hdr->ih_hcrc = htonl(checksum); 4845b1d7137Swdenk 4855b1d7137Swdenk print_header (hdr); 4865b1d7137Swdenk 4875b1d7137Swdenk (void) munmap((void *)ptr, sbuf.st_size); 4885b1d7137Swdenk 4895b1d7137Swdenk /* We're a bit of paranoid */ 490147031aeSwdenk #if defined(_POSIX_SYNCHRONIZED_IO) && !defined(__sun__) && !defined(__FreeBSD__) 4915b1d7137Swdenk (void) fdatasync (ifd); 4925b1d7137Swdenk #else 4935b1d7137Swdenk (void) fsync (ifd); 4945b1d7137Swdenk #endif 4955b1d7137Swdenk 4965b1d7137Swdenk if (close(ifd)) { 4975b1d7137Swdenk fprintf (stderr, "%s: Write error on %s: %s\n", 4985b1d7137Swdenk cmdname, imagefile, strerror(errno)); 4995b1d7137Swdenk exit (EXIT_FAILURE); 5005b1d7137Swdenk } 5015b1d7137Swdenk 5025b1d7137Swdenk exit (EXIT_SUCCESS); 5035b1d7137Swdenk } 5045b1d7137Swdenk 5055b1d7137Swdenk static void 5065b1d7137Swdenk copy_file (int ifd, const char *datafile, int pad) 5075b1d7137Swdenk { 5085b1d7137Swdenk int dfd; 5095b1d7137Swdenk struct stat sbuf; 5105b1d7137Swdenk unsigned char *ptr; 5115b1d7137Swdenk int tail; 5125b1d7137Swdenk int zero = 0; 5135b1d7137Swdenk int offset = 0; 5145b1d7137Swdenk int size; 5155b1d7137Swdenk 5165b1d7137Swdenk if (vflag) { 5175b1d7137Swdenk fprintf (stderr, "Adding Image %s\n", datafile); 5185b1d7137Swdenk } 5195b1d7137Swdenk 520ef1464ccSwdenk if ((dfd = open(datafile, O_RDONLY|O_BINARY)) < 0) { 5215b1d7137Swdenk fprintf (stderr, "%s: Can't open %s: %s\n", 5225b1d7137Swdenk cmdname, datafile, strerror(errno)); 5235b1d7137Swdenk exit (EXIT_FAILURE); 5245b1d7137Swdenk } 5255b1d7137Swdenk 5265b1d7137Swdenk if (fstat(dfd, &sbuf) < 0) { 5275b1d7137Swdenk fprintf (stderr, "%s: Can't stat %s: %s\n", 5285b1d7137Swdenk cmdname, datafile, strerror(errno)); 5295b1d7137Swdenk exit (EXIT_FAILURE); 5305b1d7137Swdenk } 5315b1d7137Swdenk 5325b1d7137Swdenk ptr = (unsigned char *)mmap(0, sbuf.st_size, 5335b1d7137Swdenk PROT_READ, MAP_SHARED, dfd, 0); 5345b1d7137Swdenk if (ptr == (unsigned char *)MAP_FAILED) { 5355b1d7137Swdenk fprintf (stderr, "%s: Can't read %s: %s\n", 5365b1d7137Swdenk cmdname, datafile, strerror(errno)); 5375b1d7137Swdenk exit (EXIT_FAILURE); 5385b1d7137Swdenk } 5395b1d7137Swdenk 5405b1d7137Swdenk if (xflag) { 5415b1d7137Swdenk unsigned char *p = NULL; 5425b1d7137Swdenk /* 5435b1d7137Swdenk * XIP: do not append the image_header_t at the 5445b1d7137Swdenk * beginning of the file, but consume the space 5455b1d7137Swdenk * reserved for it. 5465b1d7137Swdenk */ 5475b1d7137Swdenk 5485bb226e8Swdenk if ((unsigned)sbuf.st_size < sizeof(image_header_t)) { 5495b1d7137Swdenk fprintf (stderr, 5505b1d7137Swdenk "%s: Bad size: \"%s\" is too small for XIP\n", 5515b1d7137Swdenk cmdname, datafile); 5525b1d7137Swdenk exit (EXIT_FAILURE); 5535b1d7137Swdenk } 5545b1d7137Swdenk 5555b1d7137Swdenk for (p=ptr; p < ptr+sizeof(image_header_t); p++) { 5565b1d7137Swdenk if ( *p != 0xff ) { 5575b1d7137Swdenk fprintf (stderr, 5585b1d7137Swdenk "%s: Bad file: \"%s\" has invalid buffer for XIP\n", 5595b1d7137Swdenk cmdname, datafile); 5605b1d7137Swdenk exit (EXIT_FAILURE); 5615b1d7137Swdenk } 5625b1d7137Swdenk } 5635b1d7137Swdenk 5645b1d7137Swdenk offset = sizeof(image_header_t); 5655b1d7137Swdenk } 5665b1d7137Swdenk 5675b1d7137Swdenk size = sbuf.st_size - offset; 5685b1d7137Swdenk if (write(ifd, ptr + offset, size) != size) { 5695b1d7137Swdenk fprintf (stderr, "%s: Write error on %s: %s\n", 5705b1d7137Swdenk cmdname, imagefile, strerror(errno)); 5715b1d7137Swdenk exit (EXIT_FAILURE); 5725b1d7137Swdenk } 5735b1d7137Swdenk 5745b1d7137Swdenk if (pad && ((tail = size % 4) != 0)) { 5755b1d7137Swdenk 5765b1d7137Swdenk if (write(ifd, (char *)&zero, 4-tail) != 4-tail) { 5775b1d7137Swdenk fprintf (stderr, "%s: Write error on %s: %s\n", 5785b1d7137Swdenk cmdname, imagefile, strerror(errno)); 5795b1d7137Swdenk exit (EXIT_FAILURE); 5805b1d7137Swdenk } 5815b1d7137Swdenk } 5825b1d7137Swdenk 5835b1d7137Swdenk (void) munmap((void *)ptr, sbuf.st_size); 5845b1d7137Swdenk (void) close (dfd); 5855b1d7137Swdenk } 5865b1d7137Swdenk 5875b1d7137Swdenk void 5885b1d7137Swdenk usage () 5895b1d7137Swdenk { 5905b1d7137Swdenk fprintf (stderr, "Usage: %s -l image\n" 5915b1d7137Swdenk " -l ==> list image header information\n" 5925b1d7137Swdenk " %s -A arch -O os -T type -C comp " 5935b1d7137Swdenk "-a addr -e ep -n name -d data_file[:data_file...] image\n", 5945b1d7137Swdenk cmdname, cmdname); 5955b1d7137Swdenk fprintf (stderr, " -A ==> set architecture to 'arch'\n" 5965b1d7137Swdenk " -O ==> set operating system to 'os'\n" 5975b1d7137Swdenk " -T ==> set image type to 'type'\n" 5985b1d7137Swdenk " -C ==> set compression type 'comp'\n" 5995b1d7137Swdenk " -a ==> set load address to 'addr' (hex)\n" 6005b1d7137Swdenk " -e ==> set entry point to 'ep' (hex)\n" 6015b1d7137Swdenk " -n ==> set image name to 'name'\n" 6025b1d7137Swdenk " -d ==> use image data from 'datafile'\n" 6035b1d7137Swdenk " -x ==> set XIP (execute in place)\n" 6045b1d7137Swdenk ); 6055b1d7137Swdenk exit (EXIT_FAILURE); 6065b1d7137Swdenk } 6075b1d7137Swdenk 6085b1d7137Swdenk static void 6095b1d7137Swdenk print_header (image_header_t *hdr) 6105b1d7137Swdenk { 6115b1d7137Swdenk time_t timestamp; 6125b1d7137Swdenk uint32_t size; 6135b1d7137Swdenk 6145b1d7137Swdenk timestamp = (time_t)ntohl(hdr->ih_time); 6155b1d7137Swdenk size = ntohl(hdr->ih_size); 6165b1d7137Swdenk 6175b1d7137Swdenk printf ("Image Name: %.*s\n", IH_NMLEN, hdr->ih_name); 6185b1d7137Swdenk printf ("Created: %s", ctime(×tamp)); 6195b1d7137Swdenk printf ("Image Type: "); print_type(hdr); 6205b1d7137Swdenk printf ("Data Size: %d Bytes = %.2f kB = %.2f MB\n", 6215b1d7137Swdenk size, (double)size / 1.024e3, (double)size / 1.048576e6 ); 622bdccc4feSwdenk printf ("Load Address: 0x%08X\n", ntohl(hdr->ih_load)); 623bdccc4feSwdenk printf ("Entry Point: 0x%08X\n", ntohl(hdr->ih_ep)); 6245b1d7137Swdenk 6255b1d7137Swdenk if (hdr->ih_type == IH_TYPE_MULTI || hdr->ih_type == IH_TYPE_SCRIPT) { 6265b1d7137Swdenk int i, ptrs; 6275b1d7137Swdenk uint32_t pos; 6285b1d7137Swdenk unsigned long *len_ptr = (unsigned long *) ( 6295b1d7137Swdenk (unsigned long)hdr + sizeof(image_header_t) 6305b1d7137Swdenk ); 6315b1d7137Swdenk 6325b1d7137Swdenk /* determine number of images first (to calculate image offsets) */ 6335b1d7137Swdenk for (i=0; len_ptr[i]; ++i) /* null pointer terminates list */ 6345b1d7137Swdenk ; 6355b1d7137Swdenk ptrs = i; /* null pointer terminates list */ 6365b1d7137Swdenk 6375b1d7137Swdenk pos = sizeof(image_header_t) + ptrs * sizeof(long); 6385b1d7137Swdenk printf ("Contents:\n"); 6395b1d7137Swdenk for (i=0; len_ptr[i]; ++i) { 6405b1d7137Swdenk size = ntohl(len_ptr[i]); 6415b1d7137Swdenk 6425b1d7137Swdenk printf (" Image %d: %8d Bytes = %4d kB = %d MB\n", 6435b1d7137Swdenk i, size, size>>10, size>>20); 6445b1d7137Swdenk if (hdr->ih_type == IH_TYPE_SCRIPT && i > 0) { 6455b1d7137Swdenk /* 6465b1d7137Swdenk * the user may need to know offsets 6475b1d7137Swdenk * if planning to do something with 6485b1d7137Swdenk * multiple files 6495b1d7137Swdenk */ 650bdccc4feSwdenk printf (" Offset = %08X\n", pos); 6515b1d7137Swdenk } 6525b1d7137Swdenk /* copy_file() will pad the first files to even word align */ 6535b1d7137Swdenk size += 3; 6545b1d7137Swdenk size &= ~3; 6555b1d7137Swdenk pos += size; 6565b1d7137Swdenk } 6575b1d7137Swdenk } 6585b1d7137Swdenk } 6595b1d7137Swdenk 6605b1d7137Swdenk 6615b1d7137Swdenk static void 6625b1d7137Swdenk print_type (image_header_t *hdr) 6635b1d7137Swdenk { 6645b1d7137Swdenk printf ("%s %s %s (%s)\n", 6655b1d7137Swdenk put_arch (hdr->ih_arch), 6665b1d7137Swdenk put_os (hdr->ih_os ), 6675b1d7137Swdenk put_type (hdr->ih_type), 6685b1d7137Swdenk put_comp (hdr->ih_comp) 6695b1d7137Swdenk ); 6705b1d7137Swdenk } 6715b1d7137Swdenk 6725b1d7137Swdenk static char *put_arch (int arch) 6735b1d7137Swdenk { 6745b1d7137Swdenk return (put_table_entry(arch_name, "Unknown Architecture", arch)); 6755b1d7137Swdenk } 6765b1d7137Swdenk 6775b1d7137Swdenk static char *put_os (int os) 6785b1d7137Swdenk { 6795b1d7137Swdenk return (put_table_entry(os_name, "Unknown OS", os)); 6805b1d7137Swdenk } 6815b1d7137Swdenk 6825b1d7137Swdenk static char *put_type (int type) 6835b1d7137Swdenk { 6845b1d7137Swdenk return (put_table_entry(type_name, "Unknown Image", type)); 6855b1d7137Swdenk } 6865b1d7137Swdenk 6875b1d7137Swdenk static char *put_comp (int comp) 6885b1d7137Swdenk { 6895b1d7137Swdenk return (put_table_entry(comp_name, "Unknown Compression", comp)); 6905b1d7137Swdenk } 6915b1d7137Swdenk 6925b1d7137Swdenk static char *put_table_entry (table_entry_t *table, char *msg, int type) 6935b1d7137Swdenk { 6945b1d7137Swdenk for (; table->val>=0; ++table) { 6955b1d7137Swdenk if (table->val == type) 6965b1d7137Swdenk return (table->lname); 6975b1d7137Swdenk } 6985b1d7137Swdenk return (msg); 6995b1d7137Swdenk } 7005b1d7137Swdenk 7015b1d7137Swdenk static int get_arch(char *name) 7025b1d7137Swdenk { 7035b1d7137Swdenk return (get_table_entry(arch_name, "CPU", name)); 7045b1d7137Swdenk } 7055b1d7137Swdenk 7065b1d7137Swdenk 7075b1d7137Swdenk static int get_comp(char *name) 7085b1d7137Swdenk { 7095b1d7137Swdenk return (get_table_entry(comp_name, "Compression", name)); 7105b1d7137Swdenk } 7115b1d7137Swdenk 7125b1d7137Swdenk 7135b1d7137Swdenk static int get_os (char *name) 7145b1d7137Swdenk { 7155b1d7137Swdenk return (get_table_entry(os_name, "OS", name)); 7165b1d7137Swdenk } 7175b1d7137Swdenk 7185b1d7137Swdenk 7195b1d7137Swdenk static int get_type(char *name) 7205b1d7137Swdenk { 7215b1d7137Swdenk return (get_table_entry(type_name, "Image", name)); 7225b1d7137Swdenk } 7235b1d7137Swdenk 7245b1d7137Swdenk static int get_table_entry (table_entry_t *table, char *msg, char *name) 7255b1d7137Swdenk { 7265b1d7137Swdenk table_entry_t *t; 7275b1d7137Swdenk int first = 1; 7285b1d7137Swdenk 7295b1d7137Swdenk for (t=table; t->val>=0; ++t) { 7305b1d7137Swdenk if (t->sname && strcasecmp(t->sname, name)==0) 7315b1d7137Swdenk return (t->val); 7325b1d7137Swdenk } 7335b1d7137Swdenk fprintf (stderr, "\nInvalid %s Type - valid names are", msg); 7345b1d7137Swdenk for (t=table; t->val>=0; ++t) { 7355b1d7137Swdenk if (t->sname == NULL) 7365b1d7137Swdenk continue; 7375b1d7137Swdenk fprintf (stderr, "%c %s", (first) ? ':' : ',', t->sname); 7385b1d7137Swdenk first = 0; 7395b1d7137Swdenk } 7405b1d7137Swdenk fprintf (stderr, "\n"); 7415b1d7137Swdenk return (-1); 7425b1d7137Swdenk } 743