pblimage.c 7.0 KB

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