pblimage.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. /*
  2. * Copyright 2012 Freescale Semiconductor, Inc.
  3. *
  4. * See file CREDITS for list of people who contributed to this
  5. * project.
  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. #define _GNU_SOURCE
  23. #include "mkimage.h"
  24. #include <image.h>
  25. #include "pblimage.h"
  26. /*
  27. * Initialize to an invalid value.
  28. */
  29. static uint32_t next_pbl_cmd = 0x82000000;
  30. /*
  31. * need to store all bytes in memory for calculating crc32, then write the
  32. * bytes to image file for PBL boot.
  33. */
  34. static unsigned char mem_buf[1000000];
  35. static unsigned char *pmem_buf = mem_buf;
  36. static int pbl_size;
  37. static char *fname = "Unknown";
  38. static int lineno = -1;
  39. static struct pbl_header pblimage_header;
  40. static union
  41. {
  42. char c[4];
  43. unsigned char l;
  44. } endian_test = { {'l', '?', '?', 'b'} };
  45. #define ENDIANNESS ((char)endian_test.l)
  46. /*
  47. * The PBL can load up to 64 bytes at a time, so we split the U-Boot
  48. * image into 64 byte chunks. PBL needs a command for each piece, of
  49. * the form "81xxxxxx", where "xxxxxx" is the offset. Calculate the
  50. * start offset by subtracting the size of the u-boot image from the
  51. * top of the allowable 24-bit range.
  52. */
  53. static void init_next_pbl_cmd(FILE *fp_uboot)
  54. {
  55. struct stat st;
  56. int fd = fileno(fp_uboot);
  57. if (fstat(fd, &st) == -1) {
  58. printf("Error: Could not determine u-boot image size. %s\n",
  59. strerror(errno));
  60. exit(EXIT_FAILURE);
  61. }
  62. next_pbl_cmd = 0x82000000 - st.st_size;
  63. }
  64. static void generate_pbl_cmd(void)
  65. {
  66. uint32_t val = next_pbl_cmd;
  67. next_pbl_cmd += 0x40;
  68. int i;
  69. for (i = 3; i >= 0; i--) {
  70. *pmem_buf++ = (val >> (i * 8)) & 0xff;
  71. pbl_size++;
  72. }
  73. }
  74. static void pbl_fget(size_t size, FILE *stream)
  75. {
  76. unsigned char c;
  77. int c_temp;
  78. while (size && (c_temp = fgetc(stream)) != EOF) {
  79. c = (unsigned char)c_temp;
  80. *pmem_buf++ = c;
  81. pbl_size++;
  82. size--;
  83. }
  84. }
  85. /* load split u-boot with PBI command 81xxxxxx. */
  86. static void load_uboot(FILE *fp_uboot)
  87. {
  88. init_next_pbl_cmd(fp_uboot);
  89. while (next_pbl_cmd < 0x82000000) {
  90. generate_pbl_cmd();
  91. pbl_fget(64, fp_uboot);
  92. }
  93. }
  94. static void check_get_hexval(char *token)
  95. {
  96. uint32_t hexval;
  97. int i;
  98. if (!sscanf(token, "%x", &hexval)) {
  99. printf("Error:%s[%d] - Invalid hex data(%s)\n", fname,
  100. lineno, token);
  101. exit(EXIT_FAILURE);
  102. }
  103. for (i = 3; i >= 0; i--) {
  104. *pmem_buf++ = (hexval >> (i * 8)) & 0xff;
  105. pbl_size++;
  106. }
  107. }
  108. static void pbl_parser(char *name)
  109. {
  110. FILE *fd = NULL;
  111. char *line = NULL;
  112. char *token, *saveptr1, *saveptr2;
  113. size_t len = 0;
  114. fname = name;
  115. fd = fopen(name, "r");
  116. if (fd == NULL) {
  117. printf("Error:%s - Can't open\n", fname);
  118. exit(EXIT_FAILURE);
  119. }
  120. while ((getline(&line, &len, fd)) > 0) {
  121. lineno++;
  122. token = strtok_r(line, "\r\n", &saveptr1);
  123. /* drop all lines with zero tokens (= empty lines) */
  124. if (token == NULL)
  125. continue;
  126. for (line = token;; line = NULL) {
  127. token = strtok_r(line, " \t", &saveptr2);
  128. if (token == NULL)
  129. break;
  130. /* Drop all text starting with '#' as comments */
  131. if (token[0] == '#')
  132. break;
  133. check_get_hexval(token);
  134. }
  135. }
  136. if (line)
  137. free(line);
  138. fclose(fd);
  139. }
  140. static uint32_t crc_table[256];
  141. static void make_crc_table(void)
  142. {
  143. uint32_t mask;
  144. int i, j;
  145. uint32_t poly; /* polynomial exclusive-or pattern */
  146. /*
  147. * the polynomial used by PBL is 1 + x1 + x2 + x4 + x5 + x7 + x8 + x10
  148. * + x11 + x12 + x16 + x22 + x23 + x26 + x32.
  149. */
  150. poly = 0x04c11db7;
  151. for (i = 0; i < 256; i++) {
  152. mask = i << 24;
  153. for (j = 0; j < 8; j++) {
  154. if (mask & 0x80000000)
  155. mask = (mask << 1) ^ poly;
  156. else
  157. mask <<= 1;
  158. }
  159. crc_table[i] = mask;
  160. }
  161. }
  162. unsigned long pbl_crc32(unsigned long crc, const char *buf, uint32_t len)
  163. {
  164. uint32_t crc32_val = 0xffffffff;
  165. uint32_t xor = 0x0;
  166. int i;
  167. make_crc_table();
  168. for (i = 0; i < len; i++)
  169. crc32_val = (crc32_val << 8) ^
  170. crc_table[(crc32_val >> 24) ^ (*buf++ & 0xff)];
  171. crc32_val = crc32_val ^ xor;
  172. if (crc32_val < 0) {
  173. crc32_val += 0xffffffff;
  174. crc32_val += 1;
  175. }
  176. return crc32_val;
  177. }
  178. static uint32_t reverse_byte(uint32_t val)
  179. {
  180. uint32_t temp;
  181. unsigned char *p1;
  182. int j;
  183. temp = val;
  184. p1 = (unsigned char *)&temp;
  185. for (j = 3; j >= 0; j--)
  186. *p1++ = (val >> (j * 8)) & 0xff;
  187. return temp;
  188. }
  189. /* write end command and crc command to memory. */
  190. static void add_end_cmd(void)
  191. {
  192. uint32_t pbl_end_cmd[4] = {0x09138000, 0x00000000,
  193. 0x091380c0, 0x00000000};
  194. uint32_t crc32_pbl;
  195. int i;
  196. unsigned char *p = (unsigned char *)&pbl_end_cmd;
  197. if (ENDIANNESS == 'l') {
  198. for (i = 0; i < 4; i++)
  199. pbl_end_cmd[i] = reverse_byte(pbl_end_cmd[i]);
  200. }
  201. for (i = 0; i < 16; i++) {
  202. *pmem_buf++ = *p++;
  203. pbl_size++;
  204. }
  205. /* Add PBI CRC command. */
  206. *pmem_buf++ = 0x08;
  207. *pmem_buf++ = 0x13;
  208. *pmem_buf++ = 0x80;
  209. *pmem_buf++ = 0x40;
  210. pbl_size += 4;
  211. /* calculated CRC32 and write it to memory. */
  212. crc32_pbl = pbl_crc32(0, (const char *)mem_buf, pbl_size);
  213. *pmem_buf++ = (crc32_pbl >> 24) & 0xff;
  214. *pmem_buf++ = (crc32_pbl >> 16) & 0xff;
  215. *pmem_buf++ = (crc32_pbl >> 8) & 0xff;
  216. *pmem_buf++ = (crc32_pbl) & 0xff;
  217. pbl_size += 4;
  218. if ((pbl_size % 16) != 0) {
  219. for (i = 0; i < 8; i++) {
  220. *pmem_buf++ = 0x0;
  221. pbl_size++;
  222. }
  223. }
  224. if ((pbl_size % 16 != 0)) {
  225. printf("Error: Bad size of image file\n");
  226. exit(EXIT_FAILURE);
  227. }
  228. }
  229. void pbl_load_uboot(int ifd, struct mkimage_params *params)
  230. {
  231. FILE *fp_uboot;
  232. int size;
  233. /* parse the rcw.cfg file. */
  234. pbl_parser(params->imagename);
  235. /* parse the pbi.cfg file. */
  236. pbl_parser(params->imagename2);
  237. fp_uboot = fopen(params->datafile, "r");
  238. if (fp_uboot == NULL) {
  239. printf("Error: %s open failed\n", params->datafile);
  240. exit(EXIT_FAILURE);
  241. }
  242. load_uboot(fp_uboot);
  243. add_end_cmd();
  244. fclose(fp_uboot);
  245. lseek(ifd, 0, SEEK_SET);
  246. size = pbl_size;
  247. if (write(ifd, (const void *)&mem_buf, size) != size) {
  248. fprintf(stderr, "Write error on %s: %s\n",
  249. params->imagefile, strerror(errno));
  250. exit(EXIT_FAILURE);
  251. }
  252. }
  253. static int pblimage_check_image_types(uint8_t type)
  254. {
  255. if (type == IH_TYPE_PBLIMAGE)
  256. return EXIT_SUCCESS;
  257. else
  258. return EXIT_FAILURE;
  259. }
  260. static int pblimage_verify_header(unsigned char *ptr, int image_size,
  261. struct mkimage_params *params)
  262. {
  263. struct pbl_header *pbl_hdr = (struct pbl_header *) ptr;
  264. /* Only a few checks can be done: search for magic numbers */
  265. if (ENDIANNESS == 'l') {
  266. if (pbl_hdr->preamble != reverse_byte(RCW_PREAMBLE))
  267. return -FDT_ERR_BADSTRUCTURE;
  268. if (pbl_hdr->rcwheader != reverse_byte(RCW_HEADER))
  269. return -FDT_ERR_BADSTRUCTURE;
  270. } else {
  271. if (pbl_hdr->preamble != RCW_PREAMBLE)
  272. return -FDT_ERR_BADSTRUCTURE;
  273. if (pbl_hdr->rcwheader != RCW_HEADER)
  274. return -FDT_ERR_BADSTRUCTURE;
  275. }
  276. return 0;
  277. }
  278. static void pblimage_print_header(const void *ptr)
  279. {
  280. printf("Image Type: Freescale PBL Boot Image\n");
  281. }
  282. static void pblimage_set_header(void *ptr, struct stat *sbuf, int ifd,
  283. struct mkimage_params *params)
  284. {
  285. /*nothing need to do, pbl_load_uboot takes care of whole file. */
  286. }
  287. /* pblimage parameters */
  288. static struct image_type_params pblimage_params = {
  289. .name = "Freescale PBL Boot Image support",
  290. .header_size = sizeof(struct pbl_header),
  291. .hdr = (void *)&pblimage_header,
  292. .check_image_type = pblimage_check_image_types,
  293. .verify_header = pblimage_verify_header,
  294. .print_header = pblimage_print_header,
  295. .set_header = pblimage_set_header,
  296. };
  297. void init_pbl_image_type(void)
  298. {
  299. pbl_size = 0;
  300. mkimage_register(&pblimage_params);
  301. }