mkimage.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485
  1. /*
  2. * (C) Copyright 2000-2004
  3. * DENX Software Engineering
  4. * Wolfgang Denk, wd@denx.de
  5. * All rights reserved.
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License as
  9. * published by the Free Software Foundation; either version 2 of
  10. * the License, or (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  20. * MA 02111-1307 USA
  21. */
  22. #include "mkimage.h"
  23. #include <image.h>
  24. extern int errno;
  25. #ifndef MAP_FAILED
  26. #define MAP_FAILED (-1)
  27. #endif
  28. extern unsigned long crc32 (unsigned long crc, const char *buf, unsigned int len);
  29. static void copy_file (int, const char *, int);
  30. static void usage (void);
  31. char *datafile;
  32. char *imagefile;
  33. char *cmdname;
  34. int dflag = 0;
  35. int eflag = 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. image_header_t header;
  44. image_header_t *hdr = &header;
  45. int
  46. main (int argc, char **argv)
  47. {
  48. int ifd;
  49. uint32_t checksum;
  50. uint32_t addr;
  51. uint32_t ep;
  52. struct stat sbuf;
  53. unsigned char *ptr;
  54. char *name = "";
  55. cmdname = *argv;
  56. addr = ep = 0;
  57. while (--argc > 0 && **++argv == '-') {
  58. while (*++*argv) {
  59. switch (**argv) {
  60. case 'l':
  61. lflag = 1;
  62. break;
  63. case 'A':
  64. if ((--argc <= 0) ||
  65. (opt_arch = genimg_get_arch_id (*++argv)) < 0)
  66. usage ();
  67. goto NXTARG;
  68. case 'C':
  69. if ((--argc <= 0) ||
  70. (opt_comp = genimg_get_comp_id (*++argv)) < 0)
  71. usage ();
  72. goto NXTARG;
  73. case 'O':
  74. if ((--argc <= 0) ||
  75. (opt_os = genimg_get_os_id (*++argv)) < 0)
  76. usage ();
  77. goto NXTARG;
  78. case 'T':
  79. if ((--argc <= 0) ||
  80. (opt_type = genimg_get_type_id (*++argv)) < 0)
  81. usage ();
  82. goto NXTARG;
  83. case 'a':
  84. if (--argc <= 0)
  85. usage ();
  86. addr = strtoul (*++argv, (char **)&ptr, 16);
  87. if (*ptr) {
  88. fprintf (stderr,
  89. "%s: invalid load address %s\n",
  90. cmdname, *argv);
  91. exit (EXIT_FAILURE);
  92. }
  93. goto NXTARG;
  94. case 'd':
  95. if (--argc <= 0)
  96. usage ();
  97. datafile = *++argv;
  98. dflag = 1;
  99. goto NXTARG;
  100. case 'e':
  101. if (--argc <= 0)
  102. usage ();
  103. ep = strtoul (*++argv, (char **)&ptr, 16);
  104. if (*ptr) {
  105. fprintf (stderr,
  106. "%s: invalid entry point %s\n",
  107. cmdname, *argv);
  108. exit (EXIT_FAILURE);
  109. }
  110. eflag = 1;
  111. goto NXTARG;
  112. case 'n':
  113. if (--argc <= 0)
  114. usage ();
  115. name = *++argv;
  116. goto NXTARG;
  117. case 'v':
  118. vflag++;
  119. break;
  120. case 'x':
  121. xflag++;
  122. break;
  123. default:
  124. usage ();
  125. }
  126. }
  127. NXTARG: ;
  128. }
  129. if ((argc != 1) || ((lflag ^ dflag) == 0))
  130. usage();
  131. if (!eflag) {
  132. ep = addr;
  133. /* If XIP, entry point must be after the U-Boot header */
  134. if (xflag)
  135. ep += image_get_header_size ();
  136. }
  137. /*
  138. * If XIP, ensure the entry point is equal to the load address plus
  139. * the size of the U-Boot header.
  140. */
  141. if (xflag) {
  142. if (ep != addr + image_get_header_size ()) {
  143. fprintf (stderr,
  144. "%s: For XIP, the entry point must be the load addr + %lu\n",
  145. cmdname,
  146. (unsigned long)image_get_header_size ());
  147. exit (EXIT_FAILURE);
  148. }
  149. }
  150. imagefile = *argv;
  151. if (lflag) {
  152. ifd = open(imagefile, O_RDONLY|O_BINARY);
  153. } else {
  154. ifd = open(imagefile, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, 0666);
  155. }
  156. if (ifd < 0) {
  157. fprintf (stderr, "%s: Can't open %s: %s\n",
  158. cmdname, imagefile, strerror(errno));
  159. exit (EXIT_FAILURE);
  160. }
  161. if (lflag) {
  162. int len;
  163. char *data;
  164. /*
  165. * list header information of existing image
  166. */
  167. if (fstat(ifd, &sbuf) < 0) {
  168. fprintf (stderr, "%s: Can't stat %s: %s\n",
  169. cmdname, imagefile, strerror(errno));
  170. exit (EXIT_FAILURE);
  171. }
  172. if ((unsigned)sbuf.st_size < image_get_header_size ()) {
  173. fprintf (stderr,
  174. "%s: Bad size: \"%s\" is no valid image\n",
  175. cmdname, imagefile);
  176. exit (EXIT_FAILURE);
  177. }
  178. ptr = (unsigned char *)mmap(0, sbuf.st_size,
  179. PROT_READ, MAP_SHARED, ifd, 0);
  180. if ((caddr_t)ptr == (caddr_t)-1) {
  181. fprintf (stderr, "%s: Can't read %s: %s\n",
  182. cmdname, imagefile, strerror(errno));
  183. exit (EXIT_FAILURE);
  184. }
  185. /*
  186. * image_check_hcrc() creates copy of header so that
  187. * we can blank out the checksum field for checking -
  188. * this can't be done on the PROT_READ mapped data.
  189. */
  190. hdr = (image_header_t *)ptr;
  191. if (!image_check_magic (hdr)) {
  192. fprintf (stderr,
  193. "%s: Bad Magic Number: \"%s\" is no valid image\n",
  194. cmdname, imagefile);
  195. exit (EXIT_FAILURE);
  196. }
  197. if (!image_check_hcrc (hdr)) {
  198. fprintf (stderr,
  199. "%s: ERROR: \"%s\" has bad header checksum!\n",
  200. cmdname, imagefile);
  201. exit (EXIT_FAILURE);
  202. }
  203. data = (char *)image_get_data (hdr);
  204. len = sbuf.st_size - image_get_header_size ();
  205. if (crc32(0, data, len) != image_get_dcrc (hdr)) {
  206. fprintf (stderr,
  207. "%s: ERROR: \"%s\" has corrupted data!\n",
  208. cmdname, imagefile);
  209. exit (EXIT_FAILURE);
  210. }
  211. /* for multi-file images we need the data part, too */
  212. image_print_contents_noindent ((image_header_t *)ptr);
  213. (void) munmap((void *)ptr, sbuf.st_size);
  214. (void) close (ifd);
  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 = (unsigned char *)mmap(0, sbuf.st_size,
  289. PROT_READ|PROT_WRITE, MAP_SHARED, ifd, 0);
  290. if (ptr == (unsigned char *)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_noindent (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 = (unsigned char *)mmap(0, sbuf.st_size,
  353. PROT_READ, MAP_SHARED, dfd, 0);
  354. if (ptr == (unsigned char *)MAP_FAILED) {
  355. fprintf (stderr, "%s: Can't read %s: %s\n",
  356. cmdname, datafile, strerror(errno));
  357. exit (EXIT_FAILURE);
  358. }
  359. if (xflag) {
  360. unsigned char *p = NULL;
  361. /*
  362. * XIP: do not append the image_header_t at the
  363. * beginning of the file, but consume the space
  364. * reserved for it.
  365. */
  366. if ((unsigned)sbuf.st_size < image_get_header_size ()) {
  367. fprintf (stderr,
  368. "%s: Bad size: \"%s\" is too small for XIP\n",
  369. cmdname, datafile);
  370. exit (EXIT_FAILURE);
  371. }
  372. for (p = ptr; p < ptr + image_get_header_size (); p++) {
  373. if ( *p != 0xff ) {
  374. fprintf (stderr,
  375. "%s: Bad file: \"%s\" has invalid buffer for XIP\n",
  376. cmdname, datafile);
  377. exit (EXIT_FAILURE);
  378. }
  379. }
  380. offset = image_get_header_size ();
  381. }
  382. size = sbuf.st_size - offset;
  383. if (write(ifd, ptr + offset, size) != size) {
  384. fprintf (stderr, "%s: Write error on %s: %s\n",
  385. cmdname, imagefile, strerror(errno));
  386. exit (EXIT_FAILURE);
  387. }
  388. if (pad && ((tail = size % 4) != 0)) {
  389. if (write(ifd, (char *)&zero, 4-tail) != 4-tail) {
  390. fprintf (stderr, "%s: Write error on %s: %s\n",
  391. cmdname, imagefile, strerror(errno));
  392. exit (EXIT_FAILURE);
  393. }
  394. }
  395. (void) munmap((void *)ptr, sbuf.st_size);
  396. (void) close (dfd);
  397. }
  398. void
  399. usage ()
  400. {
  401. fprintf (stderr, "Usage: %s -l image\n"
  402. " -l ==> list image header information\n"
  403. " %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. cmdname, cmdname);
  406. fprintf (stderr, " -A ==> set architecture to 'arch'\n"
  407. " -O ==> set operating system to 'os'\n"
  408. " -T ==> set image type to 'type'\n"
  409. " -C ==> set compression type 'comp'\n"
  410. " -a ==> set load address to 'addr' (hex)\n"
  411. " -e ==> set entry point to 'ep' (hex)\n"
  412. " -n ==> set image name to 'name'\n"
  413. " -d ==> use image data from 'datafile'\n"
  414. " -x ==> set XIP (execute in place)\n"
  415. );
  416. exit (EXIT_FAILURE);
  417. }