mkimage.c 14 KB

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