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