mkimage.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628
  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 unsigned long crc32 (unsigned long crc, const char *buf, unsigned int len);
  27. static void copy_file (int, const char *, int);
  28. static void usage (void);
  29. static void image_verify_header (char *, int);
  30. static void fit_handle_file (void);
  31. char *datafile;
  32. char *imagefile;
  33. char *cmdname;
  34. int dflag = 0;
  35. int eflag = 0;
  36. int fflag = 0;
  37. int lflag = 0;
  38. int vflag = 0;
  39. int xflag = 0;
  40. int opt_os = IH_OS_LINUX;
  41. int opt_arch = IH_ARCH_PPC;
  42. int opt_type = IH_TYPE_KERNEL;
  43. int opt_comp = IH_COMP_GZIP;
  44. char *opt_dtc = MKIMAGE_DEFAULT_DTC_OPTIONS;
  45. image_header_t header;
  46. image_header_t *hdr = &header;
  47. int
  48. main (int argc, char **argv)
  49. {
  50. int ifd = -1;
  51. uint32_t checksum;
  52. uint32_t addr;
  53. uint32_t ep;
  54. struct stat sbuf;
  55. unsigned char *ptr;
  56. char *name = "";
  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 (fdt_check_header (ptr)) {
  202. /* old-style image */
  203. image_verify_header ((char *)ptr, sbuf.st_size);
  204. image_print_contents ((image_header_t *)ptr);
  205. } else {
  206. /* FIT image */
  207. fit_print_contents (ptr);
  208. }
  209. (void) munmap((void *)ptr, sbuf.st_size);
  210. (void) close (ifd);
  211. exit (EXIT_SUCCESS);
  212. } else if (fflag) {
  213. /* Flattened Image Tree (FIT) format handling */
  214. debug ("FIT format handling\n");
  215. fit_handle_file ();
  216. exit (EXIT_SUCCESS);
  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 char *)(ptr + image_get_header_size ()),
  298. sbuf.st_size - image_get_header_size ()
  299. );
  300. /* Build new header */
  301. image_set_magic (hdr, IH_MAGIC);
  302. image_set_time (hdr, sbuf.st_mtime);
  303. image_set_size (hdr, sbuf.st_size - image_get_header_size ());
  304. image_set_load (hdr, addr);
  305. image_set_ep (hdr, ep);
  306. image_set_dcrc (hdr, checksum);
  307. image_set_os (hdr, opt_os);
  308. image_set_arch (hdr, opt_arch);
  309. image_set_type (hdr, opt_type);
  310. image_set_comp (hdr, opt_comp);
  311. image_set_name (hdr, name);
  312. checksum = crc32 (0, (const char *)hdr, image_get_header_size ());
  313. image_set_hcrc (hdr, checksum);
  314. image_print_contents (hdr);
  315. (void) munmap((void *)ptr, sbuf.st_size);
  316. /* We're a bit of paranoid */
  317. #if defined(_POSIX_SYNCHRONIZED_IO) && !defined(__sun__) && !defined(__FreeBSD__) && !defined(__APPLE__)
  318. (void) fdatasync (ifd);
  319. #else
  320. (void) fsync (ifd);
  321. #endif
  322. if (close(ifd)) {
  323. fprintf (stderr, "%s: Write error on %s: %s\n",
  324. cmdname, imagefile, strerror(errno));
  325. exit (EXIT_FAILURE);
  326. }
  327. exit (EXIT_SUCCESS);
  328. }
  329. static void
  330. copy_file (int ifd, const char *datafile, int pad)
  331. {
  332. int dfd;
  333. struct stat sbuf;
  334. unsigned char *ptr;
  335. int tail;
  336. int zero = 0;
  337. int offset = 0;
  338. int size;
  339. if (vflag) {
  340. fprintf (stderr, "Adding Image %s\n", datafile);
  341. }
  342. if ((dfd = open(datafile, O_RDONLY|O_BINARY)) < 0) {
  343. fprintf (stderr, "%s: Can't open %s: %s\n",
  344. cmdname, datafile, strerror(errno));
  345. exit (EXIT_FAILURE);
  346. }
  347. if (fstat(dfd, &sbuf) < 0) {
  348. fprintf (stderr, "%s: Can't stat %s: %s\n",
  349. cmdname, datafile, strerror(errno));
  350. exit (EXIT_FAILURE);
  351. }
  352. ptr = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, dfd, 0);
  353. if (ptr == MAP_FAILED) {
  354. fprintf (stderr, "%s: Can't read %s: %s\n",
  355. cmdname, datafile, strerror(errno));
  356. exit (EXIT_FAILURE);
  357. }
  358. if (xflag) {
  359. unsigned char *p = NULL;
  360. /*
  361. * XIP: do not append the image_header_t at the
  362. * beginning of the file, but consume the space
  363. * reserved for it.
  364. */
  365. if ((unsigned)sbuf.st_size < image_get_header_size ()) {
  366. fprintf (stderr,
  367. "%s: Bad size: \"%s\" is too small for XIP\n",
  368. cmdname, datafile);
  369. exit (EXIT_FAILURE);
  370. }
  371. for (p = ptr; p < ptr + image_get_header_size (); p++) {
  372. if ( *p != 0xff ) {
  373. fprintf (stderr,
  374. "%s: Bad file: \"%s\" has invalid buffer for XIP\n",
  375. cmdname, datafile);
  376. exit (EXIT_FAILURE);
  377. }
  378. }
  379. offset = image_get_header_size ();
  380. }
  381. size = sbuf.st_size - offset;
  382. if (write(ifd, ptr + offset, size) != size) {
  383. fprintf (stderr, "%s: Write error on %s: %s\n",
  384. cmdname, imagefile, strerror(errno));
  385. exit (EXIT_FAILURE);
  386. }
  387. if (pad && ((tail = size % 4) != 0)) {
  388. if (write(ifd, (char *)&zero, 4-tail) != 4-tail) {
  389. fprintf (stderr, "%s: Write error on %s: %s\n",
  390. cmdname, imagefile, strerror(errno));
  391. exit (EXIT_FAILURE);
  392. }
  393. }
  394. (void) munmap((void *)ptr, sbuf.st_size);
  395. (void) close (dfd);
  396. }
  397. void
  398. usage ()
  399. {
  400. fprintf (stderr, "Usage: %s -l image\n"
  401. " -l ==> list image header information\n",
  402. cmdname);
  403. fprintf (stderr, " %s [-x] -A arch -O os -T type -C comp "
  404. "-a addr -e ep -n name -d data_file[:data_file...] image\n"
  405. " -A ==> set architecture to 'arch'\n"
  406. " -O ==> set operating system to 'os'\n"
  407. " -T ==> set image type to 'type'\n"
  408. " -C ==> set compression type 'comp'\n"
  409. " -a ==> set load address to 'addr' (hex)\n"
  410. " -e ==> set entry point to 'ep' (hex)\n"
  411. " -n ==> set image name to 'name'\n"
  412. " -d ==> use image data from 'datafile'\n"
  413. " -x ==> set XIP (execute in place)\n",
  414. cmdname);
  415. fprintf (stderr, " %s [-D dtc_options] -f fit-image.its fit-image\n",
  416. cmdname);
  417. exit (EXIT_FAILURE);
  418. }
  419. static void
  420. image_verify_header (char *ptr, int image_size)
  421. {
  422. int len;
  423. char *data;
  424. uint32_t checksum;
  425. image_header_t header;
  426. image_header_t *hdr = &header;
  427. /*
  428. * create copy of header so that we can blank out the
  429. * checksum field for checking - this can't be done
  430. * on the PROT_READ mapped data.
  431. */
  432. memcpy (hdr, ptr, sizeof(image_header_t));
  433. if (be32_to_cpu(hdr->ih_magic) != IH_MAGIC) {
  434. fprintf (stderr,
  435. "%s: Bad Magic Number: \"%s\" is no valid image\n",
  436. cmdname, imagefile);
  437. exit (EXIT_FAILURE);
  438. }
  439. data = (char *)hdr;
  440. len = sizeof(image_header_t);
  441. checksum = be32_to_cpu(hdr->ih_hcrc);
  442. hdr->ih_hcrc = cpu_to_be32(0); /* clear for re-calculation */
  443. if (crc32 (0, data, len) != checksum) {
  444. fprintf (stderr,
  445. "%s: ERROR: \"%s\" has bad header checksum!\n",
  446. cmdname, imagefile);
  447. exit (EXIT_FAILURE);
  448. }
  449. data = ptr + sizeof(image_header_t);
  450. len = image_size - sizeof(image_header_t) ;
  451. if (crc32 (0, data, len) != be32_to_cpu(hdr->ih_dcrc)) {
  452. fprintf (stderr,
  453. "%s: ERROR: \"%s\" has corrupted data!\n",
  454. cmdname, imagefile);
  455. exit (EXIT_FAILURE);
  456. }
  457. }
  458. /**
  459. * fit_handle_file - main FIT file processing function
  460. *
  461. * fit_handle_file() runs dtc to convert .its to .itb, includes
  462. * binary data, updates timestamp property and calculates hashes.
  463. *
  464. * datafile - .its file
  465. * imagefile - .itb file
  466. *
  467. * returns:
  468. * only on success, otherwise calls exit (EXIT_FAILURE);
  469. */
  470. static void fit_handle_file (void)
  471. {
  472. char tmpfile[MKIMAGE_MAX_TMPFILE_LEN];
  473. char cmd[MKIMAGE_MAX_DTC_CMDLINE_LEN];
  474. int tfd;
  475. struct stat sbuf;
  476. unsigned char *ptr;
  477. /* call dtc to include binary properties into the tmp file */
  478. if (strlen (imagefile) + strlen (MKIMAGE_TMPFILE_SUFFIX) + 1 >
  479. sizeof (tmpfile)) {
  480. fprintf (stderr, "%s: Image file name (%s) too long, "
  481. "can't create tmpfile",
  482. imagefile, cmdname);
  483. exit (EXIT_FAILURE);
  484. }
  485. sprintf (tmpfile, "%s%s", imagefile, MKIMAGE_TMPFILE_SUFFIX);
  486. /* dtc -I dts -O -p 200 datafile > tmpfile */
  487. sprintf (cmd, "%s %s %s > %s",
  488. MKIMAGE_DTC, opt_dtc, datafile, tmpfile);
  489. debug ("Trying to execute \"%s\"\n", cmd);
  490. if (system (cmd) == -1) {
  491. fprintf (stderr, "%s: system(%s) failed: %s\n",
  492. cmdname, cmd, strerror(errno));
  493. unlink (tmpfile);
  494. exit (EXIT_FAILURE);
  495. }
  496. /* load FIT blob into memory */
  497. tfd = open (tmpfile, O_RDWR|O_BINARY);
  498. if (tfd < 0) {
  499. fprintf (stderr, "%s: Can't open %s: %s\n",
  500. cmdname, tmpfile, strerror(errno));
  501. unlink (tmpfile);
  502. exit (EXIT_FAILURE);
  503. }
  504. if (fstat (tfd, &sbuf) < 0) {
  505. fprintf (stderr, "%s: Can't stat %s: %s\n",
  506. cmdname, tmpfile, strerror(errno));
  507. unlink (tmpfile);
  508. exit (EXIT_FAILURE);
  509. }
  510. ptr = mmap (0, sbuf.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, tfd, 0);
  511. if (ptr == MAP_FAILED) {
  512. fprintf (stderr, "%s: Can't read %s: %s\n",
  513. cmdname, tmpfile, strerror(errno));
  514. unlink (tmpfile);
  515. exit (EXIT_FAILURE);
  516. }
  517. /* check if ptr has a valid blob */
  518. if (fdt_check_header (ptr)) {
  519. fprintf (stderr, "%s: Invalid FIT blob\n", cmdname);
  520. unlink (tmpfile);
  521. exit (EXIT_FAILURE);
  522. }
  523. /* set hashes for images in the blob */
  524. if (fit_set_hashes (ptr)) {
  525. fprintf (stderr, "%s Can't add hashes to FIT blob", cmdname);
  526. unlink (tmpfile);
  527. exit (EXIT_FAILURE);
  528. }
  529. /* add a timestamp at offset 0 i.e., root */
  530. if (fit_set_timestamp (ptr, 0, sbuf.st_mtime)) {
  531. fprintf (stderr, "%s: Can't add image timestamp\n", cmdname);
  532. unlink (tmpfile);
  533. exit (EXIT_FAILURE);
  534. }
  535. debug ("Added timestamp successfully\n");
  536. munmap ((void *)ptr, sbuf.st_size);
  537. close (tfd);
  538. if (rename (tmpfile, imagefile) == -1) {
  539. fprintf (stderr, "%s: Can't rename %s to %s: %s\n",
  540. cmdname, tmpfile, imagefile, strerror (errno));
  541. unlink (tmpfile);
  542. unlink (imagefile);
  543. exit (EXIT_FAILURE);
  544. }
  545. }