1 /* 2 * (C) Copyright 2008 Semihalf 3 * 4 * (C) Copyright 2000-2004 5 * DENX Software Engineering 6 * Wolfgang Denk, wd@denx.de 7 * All rights reserved. 8 * 9 * This program is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU General Public License as 11 * published by the Free Software Foundation; either version 2 of 12 * the License, or (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 22 * MA 02111-1307 USA 23 */ 24 25 #include "mkimage.h" 26 #include <image.h> 27 28 extern unsigned long crc32 (unsigned long crc, const char *buf, unsigned int len); 29 static void copy_file (int, const char *, int); 30 static void usage (void); 31 static void image_verify_header (char *, int); 32 static void fit_handle_file (void); 33 34 char *datafile; 35 char *imagefile; 36 char *cmdname; 37 38 int dflag = 0; 39 int eflag = 0; 40 int fflag = 0; 41 int lflag = 0; 42 int vflag = 0; 43 int xflag = 0; 44 int opt_os = IH_OS_LINUX; 45 int opt_arch = IH_ARCH_PPC; 46 int opt_type = IH_TYPE_KERNEL; 47 int opt_comp = IH_COMP_GZIP; 48 char *opt_dtc = MKIMAGE_DEFAULT_DTC_OPTIONS; 49 50 image_header_t header; 51 image_header_t *hdr = &header; 52 53 int 54 main (int argc, char **argv) 55 { 56 int ifd = -1; 57 uint32_t checksum; 58 uint32_t addr; 59 uint32_t ep; 60 struct stat sbuf; 61 unsigned char *ptr; 62 char *name = ""; 63 64 cmdname = *argv; 65 66 addr = ep = 0; 67 68 while (--argc > 0 && **++argv == '-') { 69 while (*++*argv) { 70 switch (**argv) { 71 case 'l': 72 lflag = 1; 73 break; 74 case 'A': 75 if ((--argc <= 0) || 76 (opt_arch = genimg_get_arch_id (*++argv)) < 0) 77 usage (); 78 goto NXTARG; 79 case 'C': 80 if ((--argc <= 0) || 81 (opt_comp = genimg_get_comp_id (*++argv)) < 0) 82 usage (); 83 goto NXTARG; 84 case 'D': 85 if (--argc <= 0) 86 usage (); 87 opt_dtc = *++argv; 88 goto NXTARG; 89 90 case 'O': 91 if ((--argc <= 0) || 92 (opt_os = genimg_get_os_id (*++argv)) < 0) 93 usage (); 94 goto NXTARG; 95 case 'T': 96 if ((--argc <= 0) || 97 (opt_type = genimg_get_type_id (*++argv)) < 0) 98 usage (); 99 goto NXTARG; 100 101 case 'a': 102 if (--argc <= 0) 103 usage (); 104 addr = strtoul (*++argv, (char **)&ptr, 16); 105 if (*ptr) { 106 fprintf (stderr, 107 "%s: invalid load address %s\n", 108 cmdname, *argv); 109 exit (EXIT_FAILURE); 110 } 111 goto NXTARG; 112 case 'd': 113 if (--argc <= 0) 114 usage (); 115 datafile = *++argv; 116 dflag = 1; 117 goto NXTARG; 118 case 'e': 119 if (--argc <= 0) 120 usage (); 121 ep = strtoul (*++argv, (char **)&ptr, 16); 122 if (*ptr) { 123 fprintf (stderr, 124 "%s: invalid entry point %s\n", 125 cmdname, *argv); 126 exit (EXIT_FAILURE); 127 } 128 eflag = 1; 129 goto NXTARG; 130 case 'f': 131 if (--argc <= 0) 132 usage (); 133 datafile = *++argv; 134 fflag = 1; 135 goto NXTARG; 136 case 'n': 137 if (--argc <= 0) 138 usage (); 139 name = *++argv; 140 goto NXTARG; 141 case 'v': 142 vflag++; 143 break; 144 case 'x': 145 xflag++; 146 break; 147 default: 148 usage (); 149 } 150 } 151 NXTARG: ; 152 } 153 154 if ((argc != 1) || 155 (dflag && (fflag || lflag)) || 156 (fflag && (dflag || lflag)) || 157 (lflag && (dflag || fflag))) 158 usage(); 159 160 if (!eflag) { 161 ep = addr; 162 /* If XIP, entry point must be after the U-Boot header */ 163 if (xflag) 164 ep += image_get_header_size (); 165 } 166 167 /* 168 * If XIP, ensure the entry point is equal to the load address plus 169 * the size of the U-Boot header. 170 */ 171 if (xflag) { 172 if (ep != addr + image_get_header_size ()) { 173 fprintf (stderr, 174 "%s: For XIP, the entry point must be the load addr + %lu\n", 175 cmdname, 176 (unsigned long)image_get_header_size ()); 177 exit (EXIT_FAILURE); 178 } 179 } 180 181 imagefile = *argv; 182 183 if (!fflag){ 184 if (lflag) { 185 ifd = open (imagefile, O_RDONLY|O_BINARY); 186 } else { 187 ifd = open (imagefile, 188 O_RDWR|O_CREAT|O_TRUNC|O_BINARY, 0666); 189 } 190 191 if (ifd < 0) { 192 fprintf (stderr, "%s: Can't open %s: %s\n", 193 cmdname, imagefile, strerror(errno)); 194 exit (EXIT_FAILURE); 195 } 196 } 197 198 if (lflag) { 199 /* 200 * list header information of existing image 201 */ 202 if (fstat(ifd, &sbuf) < 0) { 203 fprintf (stderr, "%s: Can't stat %s: %s\n", 204 cmdname, imagefile, strerror(errno)); 205 exit (EXIT_FAILURE); 206 } 207 208 if ((unsigned)sbuf.st_size < image_get_header_size ()) { 209 fprintf (stderr, 210 "%s: Bad size: \"%s\" is no valid image\n", 211 cmdname, imagefile); 212 exit (EXIT_FAILURE); 213 } 214 215 ptr = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, ifd, 0); 216 if (ptr == MAP_FAILED) { 217 fprintf (stderr, "%s: Can't read %s: %s\n", 218 cmdname, imagefile, strerror(errno)); 219 exit (EXIT_FAILURE); 220 } 221 222 if (fdt_check_header (ptr)) { 223 /* old-style image */ 224 image_verify_header ((char *)ptr, sbuf.st_size); 225 image_print_contents ((image_header_t *)ptr); 226 } else { 227 /* FIT image */ 228 fit_print_contents (ptr); 229 } 230 231 (void) munmap((void *)ptr, sbuf.st_size); 232 (void) close (ifd); 233 234 exit (EXIT_SUCCESS); 235 } else if (fflag) { 236 /* Flattened Image Tree (FIT) format handling */ 237 debug ("FIT format handling\n"); 238 fit_handle_file (); 239 exit (EXIT_SUCCESS); 240 } 241 242 /* 243 * Must be -w then: 244 * 245 * write dummy header, to be fixed later 246 */ 247 memset (hdr, 0, image_get_header_size ()); 248 249 if (write(ifd, hdr, image_get_header_size ()) != image_get_header_size ()) { 250 fprintf (stderr, "%s: Write error on %s: %s\n", 251 cmdname, imagefile, strerror(errno)); 252 exit (EXIT_FAILURE); 253 } 254 255 if (opt_type == IH_TYPE_MULTI || opt_type == IH_TYPE_SCRIPT) { 256 char *file = datafile; 257 uint32_t size; 258 259 for (;;) { 260 char *sep = NULL; 261 262 if (file) { 263 if ((sep = strchr(file, ':')) != NULL) { 264 *sep = '\0'; 265 } 266 267 if (stat (file, &sbuf) < 0) { 268 fprintf (stderr, "%s: Can't stat %s: %s\n", 269 cmdname, file, strerror(errno)); 270 exit (EXIT_FAILURE); 271 } 272 size = cpu_to_uimage (sbuf.st_size); 273 } else { 274 size = 0; 275 } 276 277 if (write(ifd, (char *)&size, sizeof(size)) != sizeof(size)) { 278 fprintf (stderr, "%s: Write error on %s: %s\n", 279 cmdname, imagefile, strerror(errno)); 280 exit (EXIT_FAILURE); 281 } 282 283 if (!file) { 284 break; 285 } 286 287 if (sep) { 288 *sep = ':'; 289 file = sep + 1; 290 } else { 291 file = NULL; 292 } 293 } 294 295 file = datafile; 296 297 for (;;) { 298 char *sep = strchr(file, ':'); 299 if (sep) { 300 *sep = '\0'; 301 copy_file (ifd, file, 1); 302 *sep++ = ':'; 303 file = sep; 304 } else { 305 copy_file (ifd, file, 0); 306 break; 307 } 308 } 309 } else { 310 copy_file (ifd, datafile, 0); 311 } 312 313 /* We're a bit of paranoid */ 314 #if defined(_POSIX_SYNCHRONIZED_IO) && !defined(__sun__) && !defined(__FreeBSD__) && !defined(__APPLE__) 315 (void) fdatasync (ifd); 316 #else 317 (void) fsync (ifd); 318 #endif 319 320 if (fstat(ifd, &sbuf) < 0) { 321 fprintf (stderr, "%s: Can't stat %s: %s\n", 322 cmdname, imagefile, strerror(errno)); 323 exit (EXIT_FAILURE); 324 } 325 326 ptr = mmap(0, sbuf.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, ifd, 0); 327 if (ptr == MAP_FAILED) { 328 fprintf (stderr, "%s: Can't map %s: %s\n", 329 cmdname, imagefile, strerror(errno)); 330 exit (EXIT_FAILURE); 331 } 332 333 hdr = (image_header_t *)ptr; 334 335 checksum = crc32 (0, 336 (const char *)(ptr + image_get_header_size ()), 337 sbuf.st_size - image_get_header_size () 338 ); 339 340 /* Build new header */ 341 image_set_magic (hdr, IH_MAGIC); 342 image_set_time (hdr, sbuf.st_mtime); 343 image_set_size (hdr, sbuf.st_size - image_get_header_size ()); 344 image_set_load (hdr, addr); 345 image_set_ep (hdr, ep); 346 image_set_dcrc (hdr, checksum); 347 image_set_os (hdr, opt_os); 348 image_set_arch (hdr, opt_arch); 349 image_set_type (hdr, opt_type); 350 image_set_comp (hdr, opt_comp); 351 352 image_set_name (hdr, name); 353 354 checksum = crc32 (0, (const char *)hdr, image_get_header_size ()); 355 356 image_set_hcrc (hdr, checksum); 357 358 image_print_contents (hdr); 359 360 (void) munmap((void *)ptr, sbuf.st_size); 361 362 /* We're a bit of paranoid */ 363 #if defined(_POSIX_SYNCHRONIZED_IO) && !defined(__sun__) && !defined(__FreeBSD__) && !defined(__APPLE__) 364 (void) fdatasync (ifd); 365 #else 366 (void) fsync (ifd); 367 #endif 368 369 if (close(ifd)) { 370 fprintf (stderr, "%s: Write error on %s: %s\n", 371 cmdname, imagefile, strerror(errno)); 372 exit (EXIT_FAILURE); 373 } 374 375 exit (EXIT_SUCCESS); 376 } 377 378 static void 379 copy_file (int ifd, const char *datafile, int pad) 380 { 381 int dfd; 382 struct stat sbuf; 383 unsigned char *ptr; 384 int tail; 385 int zero = 0; 386 int offset = 0; 387 int size; 388 389 if (vflag) { 390 fprintf (stderr, "Adding Image %s\n", datafile); 391 } 392 393 if ((dfd = open(datafile, O_RDONLY|O_BINARY)) < 0) { 394 fprintf (stderr, "%s: Can't open %s: %s\n", 395 cmdname, datafile, strerror(errno)); 396 exit (EXIT_FAILURE); 397 } 398 399 if (fstat(dfd, &sbuf) < 0) { 400 fprintf (stderr, "%s: Can't stat %s: %s\n", 401 cmdname, datafile, strerror(errno)); 402 exit (EXIT_FAILURE); 403 } 404 405 ptr = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, dfd, 0); 406 if (ptr == MAP_FAILED) { 407 fprintf (stderr, "%s: Can't read %s: %s\n", 408 cmdname, datafile, strerror(errno)); 409 exit (EXIT_FAILURE); 410 } 411 412 if (xflag) { 413 unsigned char *p = NULL; 414 /* 415 * XIP: do not append the image_header_t at the 416 * beginning of the file, but consume the space 417 * reserved for it. 418 */ 419 420 if ((unsigned)sbuf.st_size < image_get_header_size ()) { 421 fprintf (stderr, 422 "%s: Bad size: \"%s\" is too small for XIP\n", 423 cmdname, datafile); 424 exit (EXIT_FAILURE); 425 } 426 427 for (p = ptr; p < ptr + image_get_header_size (); p++) { 428 if ( *p != 0xff ) { 429 fprintf (stderr, 430 "%s: Bad file: \"%s\" has invalid buffer for XIP\n", 431 cmdname, datafile); 432 exit (EXIT_FAILURE); 433 } 434 } 435 436 offset = image_get_header_size (); 437 } 438 439 size = sbuf.st_size - offset; 440 if (write(ifd, ptr + offset, size) != size) { 441 fprintf (stderr, "%s: Write error on %s: %s\n", 442 cmdname, imagefile, strerror(errno)); 443 exit (EXIT_FAILURE); 444 } 445 446 if (pad && ((tail = size % 4) != 0)) { 447 448 if (write(ifd, (char *)&zero, 4-tail) != 4-tail) { 449 fprintf (stderr, "%s: Write error on %s: %s\n", 450 cmdname, imagefile, strerror(errno)); 451 exit (EXIT_FAILURE); 452 } 453 } 454 455 (void) munmap((void *)ptr, sbuf.st_size); 456 (void) close (dfd); 457 } 458 459 void 460 usage () 461 { 462 fprintf (stderr, "Usage: %s -l image\n" 463 " -l ==> list image header information\n", 464 cmdname); 465 fprintf (stderr, " %s [-x] -A arch -O os -T type -C comp " 466 "-a addr -e ep -n name -d data_file[:data_file...] image\n" 467 " -A ==> set architecture to 'arch'\n" 468 " -O ==> set operating system to 'os'\n" 469 " -T ==> set image type to 'type'\n" 470 " -C ==> set compression type 'comp'\n" 471 " -a ==> set load address to 'addr' (hex)\n" 472 " -e ==> set entry point to 'ep' (hex)\n" 473 " -n ==> set image name to 'name'\n" 474 " -d ==> use image data from 'datafile'\n" 475 " -x ==> set XIP (execute in place)\n", 476 cmdname); 477 fprintf (stderr, " %s [-D dtc_options] -f fit-image.its fit-image\n", 478 cmdname); 479 480 exit (EXIT_FAILURE); 481 } 482 483 static void 484 image_verify_header (char *ptr, int image_size) 485 { 486 int len; 487 char *data; 488 uint32_t checksum; 489 image_header_t header; 490 image_header_t *hdr = &header; 491 492 /* 493 * create copy of header so that we can blank out the 494 * checksum field for checking - this can't be done 495 * on the PROT_READ mapped data. 496 */ 497 memcpy (hdr, ptr, sizeof(image_header_t)); 498 499 if (be32_to_cpu(hdr->ih_magic) != IH_MAGIC) { 500 fprintf (stderr, 501 "%s: Bad Magic Number: \"%s\" is no valid image\n", 502 cmdname, imagefile); 503 exit (EXIT_FAILURE); 504 } 505 506 data = (char *)hdr; 507 len = sizeof(image_header_t); 508 509 checksum = be32_to_cpu(hdr->ih_hcrc); 510 hdr->ih_hcrc = cpu_to_be32(0); /* clear for re-calculation */ 511 512 if (crc32 (0, data, len) != checksum) { 513 fprintf (stderr, 514 "%s: ERROR: \"%s\" has bad header checksum!\n", 515 cmdname, imagefile); 516 exit (EXIT_FAILURE); 517 } 518 519 data = ptr + sizeof(image_header_t); 520 len = image_size - sizeof(image_header_t) ; 521 522 if (crc32 (0, data, len) != be32_to_cpu(hdr->ih_dcrc)) { 523 fprintf (stderr, 524 "%s: ERROR: \"%s\" has corrupted data!\n", 525 cmdname, imagefile); 526 exit (EXIT_FAILURE); 527 } 528 } 529 530 /** 531 * fit_handle_file - main FIT file processing function 532 * 533 * fit_handle_file() runs dtc to convert .its to .itb, includes 534 * binary data, updates timestamp property and calculates hashes. 535 * 536 * datafile - .its file 537 * imagefile - .itb file 538 * 539 * returns: 540 * only on success, otherwise calls exit (EXIT_FAILURE); 541 */ 542 static void fit_handle_file (void) 543 { 544 char tmpfile[MKIMAGE_MAX_TMPFILE_LEN]; 545 char cmd[MKIMAGE_MAX_DTC_CMDLINE_LEN]; 546 int tfd; 547 struct stat sbuf; 548 unsigned char *ptr; 549 550 /* call dtc to include binary properties into the tmp file */ 551 if (strlen (imagefile) + strlen (MKIMAGE_TMPFILE_SUFFIX) + 1 > 552 sizeof (tmpfile)) { 553 fprintf (stderr, "%s: Image file name (%s) too long, " 554 "can't create tmpfile", 555 imagefile, cmdname); 556 exit (EXIT_FAILURE); 557 } 558 sprintf (tmpfile, "%s%s", imagefile, MKIMAGE_TMPFILE_SUFFIX); 559 560 /* dtc -I dts -O -p 200 datafile > tmpfile */ 561 sprintf (cmd, "%s %s %s > %s", 562 MKIMAGE_DTC, opt_dtc, datafile, tmpfile); 563 debug ("Trying to execute \"%s\"\n", cmd); 564 if (system (cmd) == -1) { 565 fprintf (stderr, "%s: system(%s) failed: %s\n", 566 cmdname, cmd, strerror(errno)); 567 unlink (tmpfile); 568 exit (EXIT_FAILURE); 569 } 570 571 /* load FIT blob into memory */ 572 tfd = open (tmpfile, O_RDWR|O_BINARY); 573 574 if (tfd < 0) { 575 fprintf (stderr, "%s: Can't open %s: %s\n", 576 cmdname, tmpfile, strerror(errno)); 577 unlink (tmpfile); 578 exit (EXIT_FAILURE); 579 } 580 581 if (fstat (tfd, &sbuf) < 0) { 582 fprintf (stderr, "%s: Can't stat %s: %s\n", 583 cmdname, tmpfile, strerror(errno)); 584 unlink (tmpfile); 585 exit (EXIT_FAILURE); 586 } 587 588 ptr = mmap (0, sbuf.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, tfd, 0); 589 if (ptr == MAP_FAILED) { 590 fprintf (stderr, "%s: Can't read %s: %s\n", 591 cmdname, tmpfile, strerror(errno)); 592 unlink (tmpfile); 593 exit (EXIT_FAILURE); 594 } 595 596 /* check if ptr has a valid blob */ 597 if (fdt_check_header (ptr)) { 598 fprintf (stderr, "%s: Invalid FIT blob\n", cmdname); 599 unlink (tmpfile); 600 exit (EXIT_FAILURE); 601 } 602 603 /* set hashes for images in the blob */ 604 if (fit_set_hashes (ptr)) { 605 fprintf (stderr, "%s Can't add hashes to FIT blob", cmdname); 606 unlink (tmpfile); 607 exit (EXIT_FAILURE); 608 } 609 610 /* add a timestamp at offset 0 i.e., root */ 611 if (fit_set_timestamp (ptr, 0, sbuf.st_mtime)) { 612 fprintf (stderr, "%s: Can't add image timestamp\n", cmdname); 613 unlink (tmpfile); 614 exit (EXIT_FAILURE); 615 } 616 debug ("Added timestamp successfully\n"); 617 618 munmap ((void *)ptr, sbuf.st_size); 619 close (tfd); 620 621 if (rename (tmpfile, imagefile) == -1) { 622 fprintf (stderr, "%s: Can't rename %s to %s: %s\n", 623 cmdname, tmpfile, imagefile, strerror (errno)); 624 unlink (tmpfile); 625 unlink (imagefile); 626 exit (EXIT_FAILURE); 627 } 628 } 629