pblimage.c 7.4 KB

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