1*5b1d7137Swdenk /* 2*5b1d7137Swdenk * (C) Copyright 2000-2002 3*5b1d7137Swdenk * DENX Software Engineering 4*5b1d7137Swdenk * Wolfgang Denk, wd@denx.de 5*5b1d7137Swdenk * All rights reserved. 6*5b1d7137Swdenk */ 7*5b1d7137Swdenk 8*5b1d7137Swdenk #include <errno.h> 9*5b1d7137Swdenk #include <fcntl.h> 10*5b1d7137Swdenk #include <stdio.h> 11*5b1d7137Swdenk #include <stdlib.h> 12*5b1d7137Swdenk #include <string.h> 13*5b1d7137Swdenk #ifndef __WIN32__ 14*5b1d7137Swdenk #include <netinet/in.h> /* for host / network byte order conversions */ 15*5b1d7137Swdenk #endif 16*5b1d7137Swdenk #include <sys/mman.h> 17*5b1d7137Swdenk #include <sys/stat.h> 18*5b1d7137Swdenk #include <time.h> 19*5b1d7137Swdenk #include <unistd.h> 20*5b1d7137Swdenk 21*5b1d7137Swdenk #if defined(__BEOS__) || defined(__NetBSD__) || defined(__APPLE__) 22*5b1d7137Swdenk #include <inttypes.h> 23*5b1d7137Swdenk #endif 24*5b1d7137Swdenk 25*5b1d7137Swdenk #ifdef __WIN32__ 26*5b1d7137Swdenk typedef unsigned int __u32; 27*5b1d7137Swdenk 28*5b1d7137Swdenk #define SWAP_LONG(x) \ 29*5b1d7137Swdenk ((__u32)( \ 30*5b1d7137Swdenk (((__u32)(x) & (__u32)0x000000ffUL) << 24) | \ 31*5b1d7137Swdenk (((__u32)(x) & (__u32)0x0000ff00UL) << 8) | \ 32*5b1d7137Swdenk (((__u32)(x) & (__u32)0x00ff0000UL) >> 8) | \ 33*5b1d7137Swdenk (((__u32)(x) & (__u32)0xff000000UL) >> 24) )) 34*5b1d7137Swdenk typedef unsigned char uint8_t; 35*5b1d7137Swdenk typedef unsigned short uint16_t; 36*5b1d7137Swdenk typedef unsigned int uint32_t; 37*5b1d7137Swdenk 38*5b1d7137Swdenk #define ntohl(a) SWAP_LONG(a) 39*5b1d7137Swdenk #define htonl(a) SWAP_LONG(a) 40*5b1d7137Swdenk #endif /* __WIN32__ */ 41*5b1d7137Swdenk 42*5b1d7137Swdenk #include <image.h> 43*5b1d7137Swdenk 44*5b1d7137Swdenk extern int errno; 45*5b1d7137Swdenk 46*5b1d7137Swdenk #ifndef MAP_FAILED 47*5b1d7137Swdenk #define MAP_FAILED (-1) 48*5b1d7137Swdenk #endif 49*5b1d7137Swdenk 50*5b1d7137Swdenk char *cmdname; 51*5b1d7137Swdenk 52*5b1d7137Swdenk extern unsigned long crc32 (unsigned long crc, const char *buf, unsigned int len); 53*5b1d7137Swdenk 54*5b1d7137Swdenk typedef struct table_entry { 55*5b1d7137Swdenk int val; /* as defined in image.h */ 56*5b1d7137Swdenk char *sname; /* short (input) name */ 57*5b1d7137Swdenk char *lname; /* long (output) name */ 58*5b1d7137Swdenk } table_entry_t; 59*5b1d7137Swdenk 60*5b1d7137Swdenk table_entry_t arch_name[] = { 61*5b1d7137Swdenk { IH_CPU_INVALID, NULL, "Invalid CPU", }, 62*5b1d7137Swdenk { IH_CPU_ALPHA, "alpha", "Alpha", }, 63*5b1d7137Swdenk { IH_CPU_ARM, "arm", "ARM", }, 64*5b1d7137Swdenk { IH_CPU_I386, "x86", "Intel x86", }, 65*5b1d7137Swdenk { IH_CPU_IA64, "ia64", "IA64", }, 66*5b1d7137Swdenk { IH_CPU_MIPS, "mips", "MIPS", }, 67*5b1d7137Swdenk { IH_CPU_MIPS64, "mips64", "MIPS 64 Bit", }, 68*5b1d7137Swdenk { IH_CPU_PPC, "ppc", "PowerPC", }, 69*5b1d7137Swdenk { IH_CPU_S390, "s390", "IBM S390", }, 70*5b1d7137Swdenk { IH_CPU_SH, "sh", "SuperH", }, 71*5b1d7137Swdenk { IH_CPU_SPARC, "sparc", "SPARC", }, 72*5b1d7137Swdenk { IH_CPU_SPARC64, "sparc64", "SPARC 64 Bit", }, 73*5b1d7137Swdenk { -1, "", "", }, 74*5b1d7137Swdenk }; 75*5b1d7137Swdenk 76*5b1d7137Swdenk table_entry_t os_name[] = { 77*5b1d7137Swdenk { IH_OS_INVALID, NULL, "Invalid OS", }, 78*5b1d7137Swdenk { IH_OS_OPENBSD, "openbsd", "OpenBSD", }, 79*5b1d7137Swdenk { IH_OS_NETBSD, "netbsd", "NetBSD", }, 80*5b1d7137Swdenk { IH_OS_FREEBSD, "freebsd", "FreeBSD", }, 81*5b1d7137Swdenk { IH_OS_4_4BSD, "4_4bsd", "4_4BSD", }, 82*5b1d7137Swdenk { IH_OS_LINUX, "linux", "Linux", }, 83*5b1d7137Swdenk { IH_OS_SVR4, "svr4", "SVR4", }, 84*5b1d7137Swdenk { IH_OS_ESIX, "esix", "Esix", }, 85*5b1d7137Swdenk { IH_OS_SOLARIS, "solaris", "Solaris", }, 86*5b1d7137Swdenk { IH_OS_IRIX, "irix", "Irix", }, 87*5b1d7137Swdenk { IH_OS_SCO, "sco", "SCO", }, 88*5b1d7137Swdenk { IH_OS_DELL, "dell", "Dell", }, 89*5b1d7137Swdenk { IH_OS_NCR, "ncr", "NCR", }, 90*5b1d7137Swdenk { IH_OS_LYNXOS, "lynxos", "LynxOS", }, 91*5b1d7137Swdenk { IH_OS_VXWORKS, "vxworks", "VxWorks", }, 92*5b1d7137Swdenk { IH_OS_PSOS, "psos", "pSOS", }, 93*5b1d7137Swdenk { IH_OS_QNX, "qnx", "QNX", }, 94*5b1d7137Swdenk { IH_OS_U_BOOT, "u-boot", "U-Boot", }, 95*5b1d7137Swdenk { -1, "", "", }, 96*5b1d7137Swdenk }; 97*5b1d7137Swdenk 98*5b1d7137Swdenk table_entry_t type_name[] = { 99*5b1d7137Swdenk { IH_TYPE_INVALID, NULL, "Invalid Image", }, 100*5b1d7137Swdenk { IH_TYPE_STANDALONE, "standalone", "Standalone Program", }, 101*5b1d7137Swdenk { IH_TYPE_KERNEL, "kernel", "Kernel Image", }, 102*5b1d7137Swdenk { IH_TYPE_RAMDISK, "ramdisk", "RAMDisk Image", }, 103*5b1d7137Swdenk { IH_TYPE_MULTI, "multi", "Multi-File Image", }, 104*5b1d7137Swdenk { IH_TYPE_FIRMWARE, "firmware", "Firmware", }, 105*5b1d7137Swdenk { IH_TYPE_SCRIPT, "script", "Script", }, 106*5b1d7137Swdenk { -1, "", "", }, 107*5b1d7137Swdenk }; 108*5b1d7137Swdenk 109*5b1d7137Swdenk table_entry_t comp_name[] = { 110*5b1d7137Swdenk { IH_COMP_NONE, "none", "uncompressed", }, 111*5b1d7137Swdenk { IH_COMP_GZIP, "gzip", "gzip compressed", }, 112*5b1d7137Swdenk { IH_COMP_BZIP2, "bzip2", "bzip2 compressed", }, 113*5b1d7137Swdenk { -1, "", "", }, 114*5b1d7137Swdenk }; 115*5b1d7137Swdenk 116*5b1d7137Swdenk static void copy_file (int, const char *, int); 117*5b1d7137Swdenk static void usage (void); 118*5b1d7137Swdenk static void print_header (image_header_t *); 119*5b1d7137Swdenk static void print_type (image_header_t *); 120*5b1d7137Swdenk static char *put_table_entry (table_entry_t *, char *, int); 121*5b1d7137Swdenk static char *put_arch (int); 122*5b1d7137Swdenk static char *put_type (int); 123*5b1d7137Swdenk static char *put_os (int); 124*5b1d7137Swdenk static char *put_comp (int); 125*5b1d7137Swdenk static int get_table_entry (table_entry_t *, char *, char *); 126*5b1d7137Swdenk static int get_arch(char *); 127*5b1d7137Swdenk static int get_comp(char *); 128*5b1d7137Swdenk static int get_os (char *); 129*5b1d7137Swdenk static int get_type(char *); 130*5b1d7137Swdenk 131*5b1d7137Swdenk 132*5b1d7137Swdenk char *datafile; 133*5b1d7137Swdenk char *imagefile; 134*5b1d7137Swdenk 135*5b1d7137Swdenk int dflag = 0; 136*5b1d7137Swdenk int eflag = 0; 137*5b1d7137Swdenk int lflag = 0; 138*5b1d7137Swdenk int vflag = 0; 139*5b1d7137Swdenk int xflag = 0; 140*5b1d7137Swdenk int opt_os = IH_OS_LINUX; 141*5b1d7137Swdenk int opt_arch = IH_CPU_PPC; 142*5b1d7137Swdenk int opt_type = IH_TYPE_KERNEL; 143*5b1d7137Swdenk int opt_comp = IH_COMP_GZIP; 144*5b1d7137Swdenk 145*5b1d7137Swdenk image_header_t header; 146*5b1d7137Swdenk image_header_t *hdr = &header; 147*5b1d7137Swdenk 148*5b1d7137Swdenk int 149*5b1d7137Swdenk main (int argc, char **argv) 150*5b1d7137Swdenk { 151*5b1d7137Swdenk int ifd; 152*5b1d7137Swdenk uint32_t checksum; 153*5b1d7137Swdenk uint32_t addr; 154*5b1d7137Swdenk uint32_t ep; 155*5b1d7137Swdenk struct stat sbuf; 156*5b1d7137Swdenk unsigned char *ptr; 157*5b1d7137Swdenk char *name = ""; 158*5b1d7137Swdenk 159*5b1d7137Swdenk cmdname = *argv; 160*5b1d7137Swdenk 161*5b1d7137Swdenk addr = ep = 0; 162*5b1d7137Swdenk 163*5b1d7137Swdenk while (--argc > 0 && **++argv == '-') { 164*5b1d7137Swdenk while (*++*argv) { 165*5b1d7137Swdenk switch (**argv) { 166*5b1d7137Swdenk case 'l': 167*5b1d7137Swdenk lflag = 1; 168*5b1d7137Swdenk break; 169*5b1d7137Swdenk case 'A': 170*5b1d7137Swdenk if ((--argc <= 0) || 171*5b1d7137Swdenk (opt_arch = get_arch(*++argv)) < 0) 172*5b1d7137Swdenk usage (); 173*5b1d7137Swdenk goto NXTARG; 174*5b1d7137Swdenk case 'C': 175*5b1d7137Swdenk if ((--argc <= 0) || 176*5b1d7137Swdenk (opt_comp = get_comp(*++argv)) < 0) 177*5b1d7137Swdenk usage (); 178*5b1d7137Swdenk goto NXTARG; 179*5b1d7137Swdenk case 'O': 180*5b1d7137Swdenk if ((--argc <= 0) || 181*5b1d7137Swdenk (opt_os = get_os(*++argv)) < 0) 182*5b1d7137Swdenk usage (); 183*5b1d7137Swdenk goto NXTARG; 184*5b1d7137Swdenk case 'T': 185*5b1d7137Swdenk if ((--argc <= 0) || 186*5b1d7137Swdenk (opt_type = get_type(*++argv)) < 0) 187*5b1d7137Swdenk usage (); 188*5b1d7137Swdenk goto NXTARG; 189*5b1d7137Swdenk 190*5b1d7137Swdenk case 'a': 191*5b1d7137Swdenk if (--argc <= 0) 192*5b1d7137Swdenk usage (); 193*5b1d7137Swdenk addr = strtoul (*++argv, (char **)&ptr, 16); 194*5b1d7137Swdenk if (*ptr) { 195*5b1d7137Swdenk fprintf (stderr, 196*5b1d7137Swdenk "%s: invalid load address %s\n", 197*5b1d7137Swdenk cmdname, *argv); 198*5b1d7137Swdenk exit (EXIT_FAILURE); 199*5b1d7137Swdenk } 200*5b1d7137Swdenk goto NXTARG; 201*5b1d7137Swdenk case 'd': 202*5b1d7137Swdenk if (--argc <= 0) 203*5b1d7137Swdenk usage (); 204*5b1d7137Swdenk datafile = *++argv; 205*5b1d7137Swdenk dflag = 1; 206*5b1d7137Swdenk goto NXTARG; 207*5b1d7137Swdenk case 'e': 208*5b1d7137Swdenk if (--argc <= 0) 209*5b1d7137Swdenk usage (); 210*5b1d7137Swdenk ep = strtoul (*++argv, (char **)&ptr, 16); 211*5b1d7137Swdenk if (*ptr) { 212*5b1d7137Swdenk fprintf (stderr, 213*5b1d7137Swdenk "%s: invalid entry point %s\n", 214*5b1d7137Swdenk cmdname, *argv); 215*5b1d7137Swdenk exit (EXIT_FAILURE); 216*5b1d7137Swdenk } 217*5b1d7137Swdenk eflag = 1; 218*5b1d7137Swdenk goto NXTARG; 219*5b1d7137Swdenk case 'n': 220*5b1d7137Swdenk if (--argc <= 0) 221*5b1d7137Swdenk usage (); 222*5b1d7137Swdenk name = *++argv; 223*5b1d7137Swdenk goto NXTARG; 224*5b1d7137Swdenk case 'v': 225*5b1d7137Swdenk vflag++; 226*5b1d7137Swdenk break; 227*5b1d7137Swdenk case 'x': 228*5b1d7137Swdenk xflag++; 229*5b1d7137Swdenk break; 230*5b1d7137Swdenk default: 231*5b1d7137Swdenk usage (); 232*5b1d7137Swdenk } 233*5b1d7137Swdenk } 234*5b1d7137Swdenk NXTARG: ; 235*5b1d7137Swdenk } 236*5b1d7137Swdenk 237*5b1d7137Swdenk if ((argc != 1) || ((lflag ^ dflag) == 0)) 238*5b1d7137Swdenk usage(); 239*5b1d7137Swdenk 240*5b1d7137Swdenk if (!eflag) { 241*5b1d7137Swdenk ep = addr; 242*5b1d7137Swdenk /* If XIP, entry point must be after the U-Boot header */ 243*5b1d7137Swdenk if (xflag) 244*5b1d7137Swdenk ep += sizeof(image_header_t); 245*5b1d7137Swdenk } 246*5b1d7137Swdenk 247*5b1d7137Swdenk /* 248*5b1d7137Swdenk * If XIP, ensure the entry point is equal to the load address plus 249*5b1d7137Swdenk * the size of the U-Boot header. 250*5b1d7137Swdenk */ 251*5b1d7137Swdenk if (xflag) { 252*5b1d7137Swdenk if (ep != addr + sizeof(image_header_t)) { 253*5b1d7137Swdenk fprintf (stderr, "%s: For XIP, the entry point must be the load addr + %d\n", 254*5b1d7137Swdenk cmdname, sizeof(image_header_t)); 255*5b1d7137Swdenk exit (EXIT_FAILURE); 256*5b1d7137Swdenk } 257*5b1d7137Swdenk } 258*5b1d7137Swdenk 259*5b1d7137Swdenk imagefile = *argv; 260*5b1d7137Swdenk 261*5b1d7137Swdenk if (lflag) { 262*5b1d7137Swdenk ifd = open(imagefile, O_RDONLY); 263*5b1d7137Swdenk } else { 264*5b1d7137Swdenk #ifdef __WIN32__ 265*5b1d7137Swdenk ifd = open(imagefile, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, 0666); 266*5b1d7137Swdenk #else 267*5b1d7137Swdenk ifd = open(imagefile, O_RDWR|O_CREAT|O_TRUNC, 0666); 268*5b1d7137Swdenk #endif 269*5b1d7137Swdenk } 270*5b1d7137Swdenk 271*5b1d7137Swdenk if (ifd < 0) { 272*5b1d7137Swdenk fprintf (stderr, "%s: Can't open %s: %s\n", 273*5b1d7137Swdenk cmdname, imagefile, strerror(errno)); 274*5b1d7137Swdenk exit (EXIT_FAILURE); 275*5b1d7137Swdenk } 276*5b1d7137Swdenk 277*5b1d7137Swdenk if (lflag) { 278*5b1d7137Swdenk int len; 279*5b1d7137Swdenk char *data; 280*5b1d7137Swdenk /* 281*5b1d7137Swdenk * list header information of existing image 282*5b1d7137Swdenk */ 283*5b1d7137Swdenk if (fstat(ifd, &sbuf) < 0) { 284*5b1d7137Swdenk fprintf (stderr, "%s: Can't stat %s: %s\n", 285*5b1d7137Swdenk cmdname, imagefile, strerror(errno)); 286*5b1d7137Swdenk exit (EXIT_FAILURE); 287*5b1d7137Swdenk } 288*5b1d7137Swdenk 289*5b1d7137Swdenk if (sbuf.st_size < sizeof(image_header_t)) { 290*5b1d7137Swdenk fprintf (stderr, 291*5b1d7137Swdenk "%s: Bad size: \"%s\" is no valid image\n", 292*5b1d7137Swdenk cmdname, imagefile); 293*5b1d7137Swdenk exit (EXIT_FAILURE); 294*5b1d7137Swdenk } 295*5b1d7137Swdenk 296*5b1d7137Swdenk ptr = (unsigned char *)mmap(0, sbuf.st_size, 297*5b1d7137Swdenk PROT_READ, MAP_SHARED, ifd, 0); 298*5b1d7137Swdenk if ((caddr_t)ptr == (caddr_t)-1) { 299*5b1d7137Swdenk fprintf (stderr, "%s: Can't read %s: %s\n", 300*5b1d7137Swdenk cmdname, imagefile, strerror(errno)); 301*5b1d7137Swdenk exit (EXIT_FAILURE); 302*5b1d7137Swdenk } 303*5b1d7137Swdenk 304*5b1d7137Swdenk /* 305*5b1d7137Swdenk * create copy of header so that we can blank out the 306*5b1d7137Swdenk * checksum field for checking - this can't be done 307*5b1d7137Swdenk * on the PROT_READ mapped data. 308*5b1d7137Swdenk */ 309*5b1d7137Swdenk memcpy (hdr, ptr, sizeof(image_header_t)); 310*5b1d7137Swdenk 311*5b1d7137Swdenk if (ntohl(hdr->ih_magic) != IH_MAGIC) { 312*5b1d7137Swdenk fprintf (stderr, 313*5b1d7137Swdenk "%s: Bad Magic Number: \"%s\" is no valid image\n", 314*5b1d7137Swdenk cmdname, imagefile); 315*5b1d7137Swdenk exit (EXIT_FAILURE); 316*5b1d7137Swdenk } 317*5b1d7137Swdenk 318*5b1d7137Swdenk data = (char *)hdr; 319*5b1d7137Swdenk len = sizeof(image_header_t); 320*5b1d7137Swdenk 321*5b1d7137Swdenk checksum = ntohl(hdr->ih_hcrc); 322*5b1d7137Swdenk hdr->ih_hcrc = htonl(0); /* clear for re-calculation */ 323*5b1d7137Swdenk 324*5b1d7137Swdenk if (crc32 (0, data, len) != checksum) { 325*5b1d7137Swdenk fprintf (stderr, 326*5b1d7137Swdenk "*** Warning: \"%s\" has bad header checksum!\n", 327*5b1d7137Swdenk imagefile); 328*5b1d7137Swdenk } 329*5b1d7137Swdenk 330*5b1d7137Swdenk data = (char *)(ptr + sizeof(image_header_t)); 331*5b1d7137Swdenk len = sbuf.st_size - sizeof(image_header_t) ; 332*5b1d7137Swdenk 333*5b1d7137Swdenk if (crc32 (0, data, len) != ntohl(hdr->ih_dcrc)) { 334*5b1d7137Swdenk fprintf (stderr, 335*5b1d7137Swdenk "*** Warning: \"%s\" has corrupted data!\n", 336*5b1d7137Swdenk imagefile); 337*5b1d7137Swdenk } 338*5b1d7137Swdenk 339*5b1d7137Swdenk /* for multi-file images we need the data part, too */ 340*5b1d7137Swdenk print_header ((image_header_t *)ptr); 341*5b1d7137Swdenk 342*5b1d7137Swdenk (void) munmap((void *)ptr, sbuf.st_size); 343*5b1d7137Swdenk (void) close (ifd); 344*5b1d7137Swdenk 345*5b1d7137Swdenk exit (EXIT_SUCCESS); 346*5b1d7137Swdenk } 347*5b1d7137Swdenk 348*5b1d7137Swdenk /* 349*5b1d7137Swdenk * Must be -w then: 350*5b1d7137Swdenk * 351*5b1d7137Swdenk * write dummy header, to be fixed later 352*5b1d7137Swdenk */ 353*5b1d7137Swdenk memset (hdr, 0, sizeof(image_header_t)); 354*5b1d7137Swdenk 355*5b1d7137Swdenk if (write(ifd, hdr, sizeof(image_header_t)) != sizeof(image_header_t)) { 356*5b1d7137Swdenk fprintf (stderr, "%s: Write error on %s: %s\n", 357*5b1d7137Swdenk cmdname, imagefile, strerror(errno)); 358*5b1d7137Swdenk exit (EXIT_FAILURE); 359*5b1d7137Swdenk } 360*5b1d7137Swdenk 361*5b1d7137Swdenk if (opt_type == IH_TYPE_MULTI || opt_type == IH_TYPE_SCRIPT) { 362*5b1d7137Swdenk char *file = datafile; 363*5b1d7137Swdenk unsigned long size; 364*5b1d7137Swdenk 365*5b1d7137Swdenk for (;;) { 366*5b1d7137Swdenk char *sep = NULL; 367*5b1d7137Swdenk 368*5b1d7137Swdenk if (file) { 369*5b1d7137Swdenk if ((sep = strchr(file, ':')) != NULL) { 370*5b1d7137Swdenk *sep = '\0'; 371*5b1d7137Swdenk } 372*5b1d7137Swdenk 373*5b1d7137Swdenk if (stat (file, &sbuf) < 0) { 374*5b1d7137Swdenk fprintf (stderr, "%s: Can't stat %s: %s\n", 375*5b1d7137Swdenk cmdname, file, strerror(errno)); 376*5b1d7137Swdenk exit (EXIT_FAILURE); 377*5b1d7137Swdenk } 378*5b1d7137Swdenk size = htonl(sbuf.st_size); 379*5b1d7137Swdenk } else { 380*5b1d7137Swdenk size = 0; 381*5b1d7137Swdenk } 382*5b1d7137Swdenk 383*5b1d7137Swdenk if (write(ifd, (char *)&size, sizeof(size)) != sizeof(size)) { 384*5b1d7137Swdenk fprintf (stderr, "%s: Write error on %s: %s\n", 385*5b1d7137Swdenk cmdname, imagefile, strerror(errno)); 386*5b1d7137Swdenk exit (EXIT_FAILURE); 387*5b1d7137Swdenk } 388*5b1d7137Swdenk 389*5b1d7137Swdenk if (!file) { 390*5b1d7137Swdenk break; 391*5b1d7137Swdenk } 392*5b1d7137Swdenk 393*5b1d7137Swdenk if (sep) { 394*5b1d7137Swdenk *sep = ':'; 395*5b1d7137Swdenk file = sep + 1; 396*5b1d7137Swdenk } else { 397*5b1d7137Swdenk file = NULL; 398*5b1d7137Swdenk } 399*5b1d7137Swdenk } 400*5b1d7137Swdenk 401*5b1d7137Swdenk file = datafile; 402*5b1d7137Swdenk 403*5b1d7137Swdenk for (;;) { 404*5b1d7137Swdenk char *sep = strchr(file, ':'); 405*5b1d7137Swdenk if (sep) { 406*5b1d7137Swdenk *sep = '\0'; 407*5b1d7137Swdenk copy_file (ifd, file, 1); 408*5b1d7137Swdenk *sep++ = ':'; 409*5b1d7137Swdenk file = sep; 410*5b1d7137Swdenk } else { 411*5b1d7137Swdenk copy_file (ifd, file, 0); 412*5b1d7137Swdenk break; 413*5b1d7137Swdenk } 414*5b1d7137Swdenk } 415*5b1d7137Swdenk } else { 416*5b1d7137Swdenk copy_file (ifd, datafile, 0); 417*5b1d7137Swdenk } 418*5b1d7137Swdenk 419*5b1d7137Swdenk /* We're a bit of paranoid */ 420*5b1d7137Swdenk #if defined(_POSIX_SYNCHRONIZED_IO) && !defined(__sun__) 421*5b1d7137Swdenk (void) fdatasync (ifd); 422*5b1d7137Swdenk #else 423*5b1d7137Swdenk (void) fsync (ifd); 424*5b1d7137Swdenk #endif 425*5b1d7137Swdenk 426*5b1d7137Swdenk if (fstat(ifd, &sbuf) < 0) { 427*5b1d7137Swdenk fprintf (stderr, "%s: Can't stat %s: %s\n", 428*5b1d7137Swdenk cmdname, imagefile, strerror(errno)); 429*5b1d7137Swdenk exit (EXIT_FAILURE); 430*5b1d7137Swdenk } 431*5b1d7137Swdenk 432*5b1d7137Swdenk ptr = (unsigned char *)mmap(0, sbuf.st_size, 433*5b1d7137Swdenk PROT_READ|PROT_WRITE, MAP_SHARED, ifd, 0); 434*5b1d7137Swdenk if (ptr == (unsigned char *)MAP_FAILED) { 435*5b1d7137Swdenk fprintf (stderr, "%s: Can't map %s: %s\n", 436*5b1d7137Swdenk cmdname, imagefile, strerror(errno)); 437*5b1d7137Swdenk exit (EXIT_FAILURE); 438*5b1d7137Swdenk } 439*5b1d7137Swdenk 440*5b1d7137Swdenk hdr = (image_header_t *)ptr; 441*5b1d7137Swdenk 442*5b1d7137Swdenk checksum = crc32 (0, 443*5b1d7137Swdenk (const char *)(ptr + sizeof(image_header_t)), 444*5b1d7137Swdenk sbuf.st_size - sizeof(image_header_t) 445*5b1d7137Swdenk ); 446*5b1d7137Swdenk 447*5b1d7137Swdenk /* Build new header */ 448*5b1d7137Swdenk hdr->ih_magic = htonl(IH_MAGIC); 449*5b1d7137Swdenk hdr->ih_time = htonl(sbuf.st_mtime); 450*5b1d7137Swdenk hdr->ih_size = htonl(sbuf.st_size - sizeof(image_header_t)); 451*5b1d7137Swdenk hdr->ih_load = htonl(addr); 452*5b1d7137Swdenk hdr->ih_ep = htonl(ep); 453*5b1d7137Swdenk hdr->ih_dcrc = htonl(checksum); 454*5b1d7137Swdenk hdr->ih_os = opt_os; 455*5b1d7137Swdenk hdr->ih_arch = opt_arch; 456*5b1d7137Swdenk hdr->ih_type = opt_type; 457*5b1d7137Swdenk hdr->ih_comp = opt_comp; 458*5b1d7137Swdenk 459*5b1d7137Swdenk strncpy((char *)hdr->ih_name, name, IH_NMLEN); 460*5b1d7137Swdenk 461*5b1d7137Swdenk checksum = crc32(0,(const char *)hdr,sizeof(image_header_t)); 462*5b1d7137Swdenk 463*5b1d7137Swdenk hdr->ih_hcrc = htonl(checksum); 464*5b1d7137Swdenk 465*5b1d7137Swdenk print_header (hdr); 466*5b1d7137Swdenk 467*5b1d7137Swdenk (void) munmap((void *)ptr, sbuf.st_size); 468*5b1d7137Swdenk 469*5b1d7137Swdenk /* We're a bit of paranoid */ 470*5b1d7137Swdenk #if defined(_POSIX_SYNCHRONIZED_IO) && !defined(__sun__) 471*5b1d7137Swdenk (void) fdatasync (ifd); 472*5b1d7137Swdenk #else 473*5b1d7137Swdenk (void) fsync (ifd); 474*5b1d7137Swdenk #endif 475*5b1d7137Swdenk 476*5b1d7137Swdenk if (close(ifd)) { 477*5b1d7137Swdenk fprintf (stderr, "%s: Write error on %s: %s\n", 478*5b1d7137Swdenk cmdname, imagefile, strerror(errno)); 479*5b1d7137Swdenk exit (EXIT_FAILURE); 480*5b1d7137Swdenk } 481*5b1d7137Swdenk 482*5b1d7137Swdenk exit (EXIT_SUCCESS); 483*5b1d7137Swdenk } 484*5b1d7137Swdenk 485*5b1d7137Swdenk static void 486*5b1d7137Swdenk copy_file (int ifd, const char *datafile, int pad) 487*5b1d7137Swdenk { 488*5b1d7137Swdenk int dfd; 489*5b1d7137Swdenk struct stat sbuf; 490*5b1d7137Swdenk unsigned char *ptr; 491*5b1d7137Swdenk int tail; 492*5b1d7137Swdenk int zero = 0; 493*5b1d7137Swdenk int offset = 0; 494*5b1d7137Swdenk int size; 495*5b1d7137Swdenk 496*5b1d7137Swdenk if (vflag) { 497*5b1d7137Swdenk fprintf (stderr, "Adding Image %s\n", datafile); 498*5b1d7137Swdenk } 499*5b1d7137Swdenk 500*5b1d7137Swdenk if ((dfd = open(datafile, O_RDONLY)) < 0) { 501*5b1d7137Swdenk fprintf (stderr, "%s: Can't open %s: %s\n", 502*5b1d7137Swdenk cmdname, datafile, strerror(errno)); 503*5b1d7137Swdenk exit (EXIT_FAILURE); 504*5b1d7137Swdenk } 505*5b1d7137Swdenk 506*5b1d7137Swdenk if (fstat(dfd, &sbuf) < 0) { 507*5b1d7137Swdenk fprintf (stderr, "%s: Can't stat %s: %s\n", 508*5b1d7137Swdenk cmdname, datafile, strerror(errno)); 509*5b1d7137Swdenk exit (EXIT_FAILURE); 510*5b1d7137Swdenk } 511*5b1d7137Swdenk 512*5b1d7137Swdenk ptr = (unsigned char *)mmap(0, sbuf.st_size, 513*5b1d7137Swdenk PROT_READ, MAP_SHARED, dfd, 0); 514*5b1d7137Swdenk if (ptr == (unsigned char *)MAP_FAILED) { 515*5b1d7137Swdenk fprintf (stderr, "%s: Can't read %s: %s\n", 516*5b1d7137Swdenk cmdname, datafile, strerror(errno)); 517*5b1d7137Swdenk exit (EXIT_FAILURE); 518*5b1d7137Swdenk } 519*5b1d7137Swdenk 520*5b1d7137Swdenk if (xflag) { 521*5b1d7137Swdenk unsigned char *p = NULL; 522*5b1d7137Swdenk /* 523*5b1d7137Swdenk * XIP: do not append the image_header_t at the 524*5b1d7137Swdenk * beginning of the file, but consume the space 525*5b1d7137Swdenk * reserved for it. 526*5b1d7137Swdenk */ 527*5b1d7137Swdenk 528*5b1d7137Swdenk if (sbuf.st_size < sizeof(image_header_t)) { 529*5b1d7137Swdenk fprintf (stderr, 530*5b1d7137Swdenk "%s: Bad size: \"%s\" is too small for XIP\n", 531*5b1d7137Swdenk cmdname, datafile); 532*5b1d7137Swdenk exit (EXIT_FAILURE); 533*5b1d7137Swdenk } 534*5b1d7137Swdenk 535*5b1d7137Swdenk for (p=ptr; p < ptr+sizeof(image_header_t); p++) { 536*5b1d7137Swdenk if ( *p != 0xff ) { 537*5b1d7137Swdenk fprintf (stderr, 538*5b1d7137Swdenk "%s: Bad file: \"%s\" has invalid buffer for XIP\n", 539*5b1d7137Swdenk cmdname, datafile); 540*5b1d7137Swdenk exit (EXIT_FAILURE); 541*5b1d7137Swdenk } 542*5b1d7137Swdenk } 543*5b1d7137Swdenk 544*5b1d7137Swdenk offset = sizeof(image_header_t); 545*5b1d7137Swdenk } 546*5b1d7137Swdenk 547*5b1d7137Swdenk size = sbuf.st_size - offset; 548*5b1d7137Swdenk if (write(ifd, ptr + offset, size) != size) { 549*5b1d7137Swdenk fprintf (stderr, "%s: Write error on %s: %s\n", 550*5b1d7137Swdenk cmdname, imagefile, strerror(errno)); 551*5b1d7137Swdenk exit (EXIT_FAILURE); 552*5b1d7137Swdenk } 553*5b1d7137Swdenk 554*5b1d7137Swdenk if (pad && ((tail = size % 4) != 0)) { 555*5b1d7137Swdenk 556*5b1d7137Swdenk if (write(ifd, (char *)&zero, 4-tail) != 4-tail) { 557*5b1d7137Swdenk fprintf (stderr, "%s: Write error on %s: %s\n", 558*5b1d7137Swdenk cmdname, imagefile, strerror(errno)); 559*5b1d7137Swdenk exit (EXIT_FAILURE); 560*5b1d7137Swdenk } 561*5b1d7137Swdenk } 562*5b1d7137Swdenk 563*5b1d7137Swdenk (void) munmap((void *)ptr, sbuf.st_size); 564*5b1d7137Swdenk (void) close (dfd); 565*5b1d7137Swdenk } 566*5b1d7137Swdenk 567*5b1d7137Swdenk void 568*5b1d7137Swdenk usage () 569*5b1d7137Swdenk { 570*5b1d7137Swdenk fprintf (stderr, "Usage: %s -l image\n" 571*5b1d7137Swdenk " -l ==> list image header information\n" 572*5b1d7137Swdenk " %s -A arch -O os -T type -C comp " 573*5b1d7137Swdenk "-a addr -e ep -n name -d data_file[:data_file...] image\n", 574*5b1d7137Swdenk cmdname, cmdname); 575*5b1d7137Swdenk fprintf (stderr, " -A ==> set architecture to 'arch'\n" 576*5b1d7137Swdenk " -O ==> set operating system to 'os'\n" 577*5b1d7137Swdenk " -T ==> set image type to 'type'\n" 578*5b1d7137Swdenk " -C ==> set compression type 'comp'\n" 579*5b1d7137Swdenk " -a ==> set load address to 'addr' (hex)\n" 580*5b1d7137Swdenk " -e ==> set entry point to 'ep' (hex)\n" 581*5b1d7137Swdenk " -n ==> set image name to 'name'\n" 582*5b1d7137Swdenk " -d ==> use image data from 'datafile'\n" 583*5b1d7137Swdenk " -x ==> set XIP (execute in place)\n" 584*5b1d7137Swdenk ); 585*5b1d7137Swdenk exit (EXIT_FAILURE); 586*5b1d7137Swdenk } 587*5b1d7137Swdenk 588*5b1d7137Swdenk static void 589*5b1d7137Swdenk print_header (image_header_t *hdr) 590*5b1d7137Swdenk { 591*5b1d7137Swdenk time_t timestamp; 592*5b1d7137Swdenk uint32_t size; 593*5b1d7137Swdenk 594*5b1d7137Swdenk timestamp = (time_t)ntohl(hdr->ih_time); 595*5b1d7137Swdenk size = ntohl(hdr->ih_size); 596*5b1d7137Swdenk 597*5b1d7137Swdenk printf ("Image Name: %.*s\n", IH_NMLEN, hdr->ih_name); 598*5b1d7137Swdenk printf ("Created: %s", ctime(×tamp)); 599*5b1d7137Swdenk printf ("Image Type: "); print_type(hdr); 600*5b1d7137Swdenk printf ("Data Size: %d Bytes = %.2f kB = %.2f MB\n", 601*5b1d7137Swdenk size, (double)size / 1.024e3, (double)size / 1.048576e6 ); 602*5b1d7137Swdenk printf ("Load Address: 0x%08x\n", ntohl(hdr->ih_load)); 603*5b1d7137Swdenk printf ("Entry Point: 0x%08x\n", ntohl(hdr->ih_ep)); 604*5b1d7137Swdenk 605*5b1d7137Swdenk if (hdr->ih_type == IH_TYPE_MULTI || hdr->ih_type == IH_TYPE_SCRIPT) { 606*5b1d7137Swdenk int i, ptrs; 607*5b1d7137Swdenk uint32_t pos; 608*5b1d7137Swdenk unsigned long *len_ptr = (unsigned long *) ( 609*5b1d7137Swdenk (unsigned long)hdr + sizeof(image_header_t) 610*5b1d7137Swdenk ); 611*5b1d7137Swdenk 612*5b1d7137Swdenk /* determine number of images first (to calculate image offsets) */ 613*5b1d7137Swdenk for (i=0; len_ptr[i]; ++i) /* null pointer terminates list */ 614*5b1d7137Swdenk ; 615*5b1d7137Swdenk ptrs = i; /* null pointer terminates list */ 616*5b1d7137Swdenk 617*5b1d7137Swdenk pos = sizeof(image_header_t) + ptrs * sizeof(long); 618*5b1d7137Swdenk printf ("Contents:\n"); 619*5b1d7137Swdenk for (i=0; len_ptr[i]; ++i) { 620*5b1d7137Swdenk size = ntohl(len_ptr[i]); 621*5b1d7137Swdenk 622*5b1d7137Swdenk printf (" Image %d: %8d Bytes = %4d kB = %d MB\n", 623*5b1d7137Swdenk i, size, size>>10, size>>20); 624*5b1d7137Swdenk if (hdr->ih_type == IH_TYPE_SCRIPT && i > 0) { 625*5b1d7137Swdenk /* 626*5b1d7137Swdenk * the user may need to know offsets 627*5b1d7137Swdenk * if planning to do something with 628*5b1d7137Swdenk * multiple files 629*5b1d7137Swdenk */ 630*5b1d7137Swdenk printf (" Offset = %08x\n", pos); 631*5b1d7137Swdenk } 632*5b1d7137Swdenk /* copy_file() will pad the first files to even word align */ 633*5b1d7137Swdenk size += 3; 634*5b1d7137Swdenk size &= ~3; 635*5b1d7137Swdenk pos += size; 636*5b1d7137Swdenk } 637*5b1d7137Swdenk } 638*5b1d7137Swdenk } 639*5b1d7137Swdenk 640*5b1d7137Swdenk 641*5b1d7137Swdenk static void 642*5b1d7137Swdenk print_type (image_header_t *hdr) 643*5b1d7137Swdenk { 644*5b1d7137Swdenk printf ("%s %s %s (%s)\n", 645*5b1d7137Swdenk put_arch (hdr->ih_arch), 646*5b1d7137Swdenk put_os (hdr->ih_os ), 647*5b1d7137Swdenk put_type (hdr->ih_type), 648*5b1d7137Swdenk put_comp (hdr->ih_comp) 649*5b1d7137Swdenk ); 650*5b1d7137Swdenk } 651*5b1d7137Swdenk 652*5b1d7137Swdenk static char *put_arch (int arch) 653*5b1d7137Swdenk { 654*5b1d7137Swdenk return (put_table_entry(arch_name, "Unknown Architecture", arch)); 655*5b1d7137Swdenk } 656*5b1d7137Swdenk 657*5b1d7137Swdenk static char *put_os (int os) 658*5b1d7137Swdenk { 659*5b1d7137Swdenk return (put_table_entry(os_name, "Unknown OS", os)); 660*5b1d7137Swdenk } 661*5b1d7137Swdenk 662*5b1d7137Swdenk static char *put_type (int type) 663*5b1d7137Swdenk { 664*5b1d7137Swdenk return (put_table_entry(type_name, "Unknown Image", type)); 665*5b1d7137Swdenk } 666*5b1d7137Swdenk 667*5b1d7137Swdenk static char *put_comp (int comp) 668*5b1d7137Swdenk { 669*5b1d7137Swdenk return (put_table_entry(comp_name, "Unknown Compression", comp)); 670*5b1d7137Swdenk } 671*5b1d7137Swdenk 672*5b1d7137Swdenk static char *put_table_entry (table_entry_t *table, char *msg, int type) 673*5b1d7137Swdenk { 674*5b1d7137Swdenk for (; table->val>=0; ++table) { 675*5b1d7137Swdenk if (table->val == type) 676*5b1d7137Swdenk return (table->lname); 677*5b1d7137Swdenk } 678*5b1d7137Swdenk return (msg); 679*5b1d7137Swdenk } 680*5b1d7137Swdenk 681*5b1d7137Swdenk static int get_arch(char *name) 682*5b1d7137Swdenk { 683*5b1d7137Swdenk return (get_table_entry(arch_name, "CPU", name)); 684*5b1d7137Swdenk } 685*5b1d7137Swdenk 686*5b1d7137Swdenk 687*5b1d7137Swdenk static int get_comp(char *name) 688*5b1d7137Swdenk { 689*5b1d7137Swdenk return (get_table_entry(comp_name, "Compression", name)); 690*5b1d7137Swdenk } 691*5b1d7137Swdenk 692*5b1d7137Swdenk 693*5b1d7137Swdenk static int get_os (char *name) 694*5b1d7137Swdenk { 695*5b1d7137Swdenk return (get_table_entry(os_name, "OS", name)); 696*5b1d7137Swdenk } 697*5b1d7137Swdenk 698*5b1d7137Swdenk 699*5b1d7137Swdenk static int get_type(char *name) 700*5b1d7137Swdenk { 701*5b1d7137Swdenk return (get_table_entry(type_name, "Image", name)); 702*5b1d7137Swdenk } 703*5b1d7137Swdenk 704*5b1d7137Swdenk static int get_table_entry (table_entry_t *table, char *msg, char *name) 705*5b1d7137Swdenk { 706*5b1d7137Swdenk table_entry_t *t; 707*5b1d7137Swdenk int first = 1; 708*5b1d7137Swdenk 709*5b1d7137Swdenk for (t=table; t->val>=0; ++t) { 710*5b1d7137Swdenk if (t->sname && strcasecmp(t->sname, name)==0) 711*5b1d7137Swdenk return (t->val); 712*5b1d7137Swdenk } 713*5b1d7137Swdenk fprintf (stderr, "\nInvalid %s Type - valid names are", msg); 714*5b1d7137Swdenk for (t=table; t->val>=0; ++t) { 715*5b1d7137Swdenk if (t->sname == NULL) 716*5b1d7137Swdenk continue; 717*5b1d7137Swdenk fprintf (stderr, "%c %s", (first) ? ':' : ',', t->sname); 718*5b1d7137Swdenk first = 0; 719*5b1d7137Swdenk } 720*5b1d7137Swdenk fprintf (stderr, "\n"); 721*5b1d7137Swdenk return (-1); 722*5b1d7137Swdenk } 723