mkimage.c 15 KB

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