pblimage.c 6.2 KB

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