mkimage.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634
  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 (void *)(-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 = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, ifd, 0);
  200. if (ptr == MAP_FAILED) {
  201. fprintf (stderr, "%s: Can't read %s: %s\n",
  202. cmdname, imagefile, strerror(errno));
  203. exit (EXIT_FAILURE);
  204. }
  205. if (fdt_check_header (ptr)) {
  206. /* old-style image */
  207. image_verify_header ((char *)ptr, sbuf.st_size);
  208. image_print_contents ((image_header_t *)ptr);
  209. } else {
  210. /* FIT image */
  211. fit_print_contents (ptr);
  212. }
  213. (void) munmap((void *)ptr, sbuf.st_size);
  214. (void) close (ifd);
  215. exit (EXIT_SUCCESS);
  216. } else if (fflag) {
  217. /* Flattened Image Tree (FIT) format handling */
  218. debug ("FIT format handling\n");
  219. fit_handle_file ();
  220. exit (EXIT_SUCCESS);
  221. }
  222. /*
  223. * Must be -w then:
  224. *
  225. * write dummy header, to be fixed later
  226. */
  227. memset (hdr, 0, image_get_header_size ());
  228. if (write(ifd, hdr, image_get_header_size ()) != image_get_header_size ()) {
  229. fprintf (stderr, "%s: Write error on %s: %s\n",
  230. cmdname, imagefile, strerror(errno));
  231. exit (EXIT_FAILURE);
  232. }
  233. if (opt_type == IH_TYPE_MULTI || opt_type == IH_TYPE_SCRIPT) {
  234. char *file = datafile;
  235. uint32_t size;
  236. for (;;) {
  237. char *sep = NULL;
  238. if (file) {
  239. if ((sep = strchr(file, ':')) != NULL) {
  240. *sep = '\0';
  241. }
  242. if (stat (file, &sbuf) < 0) {
  243. fprintf (stderr, "%s: Can't stat %s: %s\n",
  244. cmdname, file, strerror(errno));
  245. exit (EXIT_FAILURE);
  246. }
  247. size = cpu_to_uimage (sbuf.st_size);
  248. } else {
  249. size = 0;
  250. }
  251. if (write(ifd, (char *)&size, sizeof(size)) != sizeof(size)) {
  252. fprintf (stderr, "%s: Write error on %s: %s\n",
  253. cmdname, imagefile, strerror(errno));
  254. exit (EXIT_FAILURE);
  255. }
  256. if (!file) {
  257. break;
  258. }
  259. if (sep) {
  260. *sep = ':';
  261. file = sep + 1;
  262. } else {
  263. file = NULL;
  264. }
  265. }
  266. file = datafile;
  267. for (;;) {
  268. char *sep = strchr(file, ':');
  269. if (sep) {
  270. *sep = '\0';
  271. copy_file (ifd, file, 1);
  272. *sep++ = ':';
  273. file = sep;
  274. } else {
  275. copy_file (ifd, file, 0);
  276. break;
  277. }
  278. }
  279. } else {
  280. copy_file (ifd, datafile, 0);
  281. }
  282. /* We're a bit of paranoid */
  283. #if defined(_POSIX_SYNCHRONIZED_IO) && !defined(__sun__) && !defined(__FreeBSD__) && !defined(__APPLE__)
  284. (void) fdatasync (ifd);
  285. #else
  286. (void) fsync (ifd);
  287. #endif
  288. if (fstat(ifd, &sbuf) < 0) {
  289. fprintf (stderr, "%s: Can't stat %s: %s\n",
  290. cmdname, imagefile, strerror(errno));
  291. exit (EXIT_FAILURE);
  292. }
  293. ptr = mmap(0, sbuf.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, ifd, 0);
  294. if (ptr == MAP_FAILED) {
  295. fprintf (stderr, "%s: Can't map %s: %s\n",
  296. cmdname, imagefile, strerror(errno));
  297. exit (EXIT_FAILURE);
  298. }
  299. hdr = (image_header_t *)ptr;
  300. checksum = crc32 (0,
  301. (const char *)(ptr + image_get_header_size ()),
  302. sbuf.st_size - image_get_header_size ()
  303. );
  304. /* Build new header */
  305. image_set_magic (hdr, IH_MAGIC);
  306. image_set_time (hdr, sbuf.st_mtime);
  307. image_set_size (hdr, sbuf.st_size - image_get_header_size ());
  308. image_set_load (hdr, addr);
  309. image_set_ep (hdr, ep);
  310. image_set_dcrc (hdr, checksum);
  311. image_set_os (hdr, opt_os);
  312. image_set_arch (hdr, opt_arch);
  313. image_set_type (hdr, opt_type);
  314. image_set_comp (hdr, opt_comp);
  315. image_set_name (hdr, name);
  316. checksum = crc32 (0, (const char *)hdr, image_get_header_size ());
  317. image_set_hcrc (hdr, checksum);
  318. image_print_contents (hdr);
  319. (void) munmap((void *)ptr, sbuf.st_size);
  320. /* We're a bit of paranoid */
  321. #if defined(_POSIX_SYNCHRONIZED_IO) && !defined(__sun__) && !defined(__FreeBSD__) && !defined(__APPLE__)
  322. (void) fdatasync (ifd);
  323. #else
  324. (void) fsync (ifd);
  325. #endif
  326. if (close(ifd)) {
  327. fprintf (stderr, "%s: Write error on %s: %s\n",
  328. cmdname, imagefile, strerror(errno));
  329. exit (EXIT_FAILURE);
  330. }
  331. exit (EXIT_SUCCESS);
  332. }
  333. static void
  334. copy_file (int ifd, const char *datafile, int pad)
  335. {
  336. int dfd;
  337. struct stat sbuf;
  338. unsigned char *ptr;
  339. int tail;
  340. int zero = 0;
  341. int offset = 0;
  342. int size;
  343. if (vflag) {
  344. fprintf (stderr, "Adding Image %s\n", datafile);
  345. }
  346. if ((dfd = open(datafile, O_RDONLY|O_BINARY)) < 0) {
  347. fprintf (stderr, "%s: Can't open %s: %s\n",
  348. cmdname, datafile, strerror(errno));
  349. exit (EXIT_FAILURE);
  350. }
  351. if (fstat(dfd, &sbuf) < 0) {
  352. fprintf (stderr, "%s: Can't stat %s: %s\n",
  353. cmdname, datafile, strerror(errno));
  354. exit (EXIT_FAILURE);
  355. }
  356. ptr = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, dfd, 0);
  357. if (ptr == MAP_FAILED) {
  358. fprintf (stderr, "%s: Can't read %s: %s\n",
  359. cmdname, datafile, strerror(errno));
  360. exit (EXIT_FAILURE);
  361. }
  362. if (xflag) {
  363. unsigned char *p = NULL;
  364. /*
  365. * XIP: do not append the image_header_t at the
  366. * beginning of the file, but consume the space
  367. * reserved for it.
  368. */
  369. if ((unsigned)sbuf.st_size < image_get_header_size ()) {
  370. fprintf (stderr,
  371. "%s: Bad size: \"%s\" is too small for XIP\n",
  372. cmdname, datafile);
  373. exit (EXIT_FAILURE);
  374. }
  375. for (p = ptr; p < ptr + image_get_header_size (); p++) {
  376. if ( *p != 0xff ) {
  377. fprintf (stderr,
  378. "%s: Bad file: \"%s\" has invalid buffer for XIP\n",
  379. cmdname, datafile);
  380. exit (EXIT_FAILURE);
  381. }
  382. }
  383. offset = image_get_header_size ();
  384. }
  385. size = sbuf.st_size - offset;
  386. if (write(ifd, ptr + offset, size) != size) {
  387. fprintf (stderr, "%s: Write error on %s: %s\n",
  388. cmdname, imagefile, strerror(errno));
  389. exit (EXIT_FAILURE);
  390. }
  391. if (pad && ((tail = size % 4) != 0)) {
  392. if (write(ifd, (char *)&zero, 4-tail) != 4-tail) {
  393. fprintf (stderr, "%s: Write error on %s: %s\n",
  394. cmdname, imagefile, strerror(errno));
  395. exit (EXIT_FAILURE);
  396. }
  397. }
  398. (void) munmap((void *)ptr, sbuf.st_size);
  399. (void) close (dfd);
  400. }
  401. void
  402. usage ()
  403. {
  404. fprintf (stderr, "Usage: %s -l image\n"
  405. " -l ==> list image header information\n",
  406. cmdname);
  407. fprintf (stderr, " %s [-x] -A arch -O os -T type -C comp "
  408. "-a addr -e ep -n name -d data_file[:data_file...] image\n"
  409. " -A ==> set architecture to 'arch'\n"
  410. " -O ==> set operating system to 'os'\n"
  411. " -T ==> set image type to 'type'\n"
  412. " -C ==> set compression type 'comp'\n"
  413. " -a ==> set load address to 'addr' (hex)\n"
  414. " -e ==> set entry point to 'ep' (hex)\n"
  415. " -n ==> set image name to 'name'\n"
  416. " -d ==> use image data from 'datafile'\n"
  417. " -x ==> set XIP (execute in place)\n",
  418. cmdname);
  419. fprintf (stderr, " %s [-D dtc_options] -f fit-image.its fit-image\n",
  420. cmdname);
  421. exit (EXIT_FAILURE);
  422. }
  423. static void
  424. image_verify_header (char *ptr, int image_size)
  425. {
  426. int len;
  427. char *data;
  428. uint32_t checksum;
  429. image_header_t header;
  430. image_header_t *hdr = &header;
  431. /*
  432. * create copy of header so that we can blank out the
  433. * checksum field for checking - this can't be done
  434. * on the PROT_READ mapped data.
  435. */
  436. memcpy (hdr, ptr, sizeof(image_header_t));
  437. if (ntohl(hdr->ih_magic) != IH_MAGIC) {
  438. fprintf (stderr,
  439. "%s: Bad Magic Number: \"%s\" is no valid image\n",
  440. cmdname, imagefile);
  441. exit (EXIT_FAILURE);
  442. }
  443. data = (char *)hdr;
  444. len = sizeof(image_header_t);
  445. checksum = ntohl(hdr->ih_hcrc);
  446. hdr->ih_hcrc = htonl(0); /* clear for re-calculation */
  447. if (crc32 (0, data, len) != checksum) {
  448. fprintf (stderr,
  449. "%s: ERROR: \"%s\" has bad header checksum!\n",
  450. cmdname, imagefile);
  451. exit (EXIT_FAILURE);
  452. }
  453. data = ptr + sizeof(image_header_t);
  454. len = image_size - sizeof(image_header_t) ;
  455. if (crc32 (0, data, len) != ntohl(hdr->ih_dcrc)) {
  456. fprintf (stderr,
  457. "%s: ERROR: \"%s\" has corrupted data!\n",
  458. cmdname, imagefile);
  459. exit (EXIT_FAILURE);
  460. }
  461. }
  462. /**
  463. * fit_handle_file - main FIT file processing function
  464. *
  465. * fit_handle_file() runs dtc to convert .its to .itb, includes
  466. * binary data, updates timestamp property and calculates hashes.
  467. *
  468. * datafile - .its file
  469. * imagefile - .itb file
  470. *
  471. * returns:
  472. * only on success, otherwise calls exit (EXIT_FAILURE);
  473. */
  474. static void fit_handle_file (void)
  475. {
  476. char tmpfile[MKIMAGE_MAX_TMPFILE_LEN];
  477. char cmd[MKIMAGE_MAX_DTC_CMDLINE_LEN];
  478. int tfd;
  479. struct stat sbuf;
  480. unsigned char *ptr;
  481. /* call dtc to include binary properties into the tmp file */
  482. if (strlen (imagefile) + strlen (MKIMAGE_TMPFILE_SUFFIX) + 1 >
  483. sizeof (tmpfile)) {
  484. fprintf (stderr, "%s: Image file name (%s) too long, "
  485. "can't create tmpfile",
  486. imagefile, cmdname);
  487. exit (EXIT_FAILURE);
  488. }
  489. sprintf (tmpfile, "%s%s", imagefile, MKIMAGE_TMPFILE_SUFFIX);
  490. /* dtc -I dts -O -p 200 datafile > tmpfile */
  491. sprintf (cmd, "%s %s %s > %s",
  492. MKIMAGE_DTC, opt_dtc, datafile, tmpfile);
  493. debug ("Trying to execute \"%s\"\n", cmd);
  494. if (system (cmd) == -1) {
  495. fprintf (stderr, "%s: system(%s) failed: %s\n",
  496. cmdname, cmd, strerror(errno));
  497. unlink (tmpfile);
  498. exit (EXIT_FAILURE);
  499. }
  500. /* load FIT blob into memory */
  501. tfd = open (tmpfile, O_RDWR|O_BINARY);
  502. if (tfd < 0) {
  503. fprintf (stderr, "%s: Can't open %s: %s\n",
  504. cmdname, tmpfile, strerror(errno));
  505. unlink (tmpfile);
  506. exit (EXIT_FAILURE);
  507. }
  508. if (fstat (tfd, &sbuf) < 0) {
  509. fprintf (stderr, "%s: Can't stat %s: %s\n",
  510. cmdname, tmpfile, strerror(errno));
  511. unlink (tmpfile);
  512. exit (EXIT_FAILURE);
  513. }
  514. ptr = mmap (0, sbuf.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, tfd, 0);
  515. if (ptr == MAP_FAILED) {
  516. fprintf (stderr, "%s: Can't read %s: %s\n",
  517. cmdname, tmpfile, strerror(errno));
  518. unlink (tmpfile);
  519. exit (EXIT_FAILURE);
  520. }
  521. /* check if ptr has a valid blob */
  522. if (fdt_check_header (ptr)) {
  523. fprintf (stderr, "%s: Invalid FIT blob\n", cmdname);
  524. unlink (tmpfile);
  525. exit (EXIT_FAILURE);
  526. }
  527. /* set hashes for images in the blob */
  528. if (fit_set_hashes (ptr)) {
  529. fprintf (stderr, "%s Can't add hashes to FIT blob", cmdname);
  530. unlink (tmpfile);
  531. exit (EXIT_FAILURE);
  532. }
  533. /* add a timestamp at offset 0 i.e., root */
  534. if (fit_set_timestamp (ptr, 0, sbuf.st_mtime)) {
  535. fprintf (stderr, "%s: Can't add image timestamp\n", cmdname);
  536. unlink (tmpfile);
  537. exit (EXIT_FAILURE);
  538. }
  539. debug ("Added timestamp successfully\n");
  540. munmap ((void *)ptr, sbuf.st_size);
  541. close (tfd);
  542. if (rename (tmpfile, imagefile) == -1) {
  543. fprintf (stderr, "%s: Can't rename %s to %s: %s\n",
  544. cmdname, tmpfile, imagefile, strerror (errno));
  545. unlink (tmpfile);
  546. unlink (imagefile);
  547. exit (EXIT_FAILURE);
  548. }
  549. }