mkimage.c 15 KB

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