pblimage.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright 2012-2014 Freescale Semiconductor, Inc.
  4. */
  5. #include "imagetool.h"
  6. #include <image.h>
  7. #include "pblimage.h"
  8. #include "pbl_crc32.h"
  9. #include <u-boot/crc.h>
  10. #define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
  11. #define PBL_ACS_CONT_CMD 0x81000000
  12. #define PBL_ADDR_24BIT_MASK 0x00ffffff
  13. /*
  14. * Initialize to an invalid value.
  15. */
  16. static uint32_t next_pbl_cmd = 0x82000000;
  17. /*
  18. * need to store all bytes in memory for calculating crc32, then write the
  19. * bytes to image file for PBL boot.
  20. */
  21. static unsigned char mem_buf[1000000];
  22. static unsigned char *pmem_buf = mem_buf;
  23. static int pbl_size;
  24. static char *fname = "Unknown";
  25. static int lineno = -1;
  26. static struct pbl_header pblimage_header;
  27. static int uboot_size;
  28. static int arch_flag;
  29. static uint32_t pbl_cmd_initaddr;
  30. static uint32_t pbi_crc_cmd1;
  31. static uint32_t pbi_crc_cmd2;
  32. static uint32_t pbl_end_cmd[4];
  33. static union
  34. {
  35. char c[4];
  36. unsigned char l;
  37. } endian_test = { {'l', '?', '?', 'b'} };
  38. #define ENDIANNESS ((char)endian_test.l)
  39. /*
  40. * The PBL can load up to 64 bytes at a time, so we split the U-Boot
  41. * image into 64 byte chunks. PBL needs a command for each piece, of
  42. * the form "81xxxxxx", where "xxxxxx" is the offset. Calculate the
  43. * start offset by subtracting the size of the u-boot image from the
  44. * top of the allowable 24-bit range.
  45. */
  46. static void generate_pbl_cmd(void)
  47. {
  48. uint32_t val = next_pbl_cmd;
  49. next_pbl_cmd += 0x40;
  50. int i;
  51. for (i = 3; i >= 0; i--) {
  52. *pmem_buf++ = (val >> (i * 8)) & 0xff;
  53. pbl_size++;
  54. }
  55. }
  56. static void pbl_fget(size_t size, FILE *stream)
  57. {
  58. unsigned char c = 0xff;
  59. int c_temp;
  60. while (size) {
  61. c_temp = fgetc(stream);
  62. if (c_temp != EOF)
  63. c = (unsigned char)c_temp;
  64. else if ((c_temp == EOF) && (arch_flag == IH_ARCH_ARM))
  65. c = 0xff;
  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. next_pbl_cmd = pbl_cmd_initaddr - uboot_size;
  75. while (next_pbl_cmd < pbl_cmd_initaddr) {
  76. generate_pbl_cmd();
  77. pbl_fget(64, fp_uboot);
  78. }
  79. }
  80. static void check_get_hexval(char *token)
  81. {
  82. uint32_t hexval;
  83. int i;
  84. if (!sscanf(token, "%x", &hexval)) {
  85. printf("Error:%s[%d] - Invalid hex data(%s)\n", fname,
  86. lineno, token);
  87. exit(EXIT_FAILURE);
  88. }
  89. for (i = 3; i >= 0; i--) {
  90. *pmem_buf++ = (hexval >> (i * 8)) & 0xff;
  91. pbl_size++;
  92. }
  93. }
  94. static void pbl_parser(char *name)
  95. {
  96. FILE *fd = NULL;
  97. char *line = NULL;
  98. char *token, *saveptr1, *saveptr2;
  99. size_t len = 0;
  100. fname = name;
  101. fd = fopen(name, "r");
  102. if (fd == NULL) {
  103. printf("Error:%s - Can't open\n", fname);
  104. exit(EXIT_FAILURE);
  105. }
  106. while ((getline(&line, &len, fd)) > 0) {
  107. lineno++;
  108. token = strtok_r(line, "\r\n", &saveptr1);
  109. /* drop all lines with zero tokens (= empty lines) */
  110. if (token == NULL)
  111. continue;
  112. for (line = token;; line = NULL) {
  113. token = strtok_r(line, " \t", &saveptr2);
  114. if (token == NULL)
  115. break;
  116. /* Drop all text starting with '#' as comments */
  117. if (token[0] == '#')
  118. break;
  119. check_get_hexval(token);
  120. }
  121. }
  122. if (line)
  123. free(line);
  124. fclose(fd);
  125. }
  126. static uint32_t reverse_byte(uint32_t val)
  127. {
  128. uint32_t temp;
  129. unsigned char *p1;
  130. int j;
  131. temp = val;
  132. p1 = (unsigned char *)&temp;
  133. for (j = 3; j >= 0; j--)
  134. *p1++ = (val >> (j * 8)) & 0xff;
  135. return temp;
  136. }
  137. /* write end command and crc command to memory. */
  138. static void add_end_cmd(void)
  139. {
  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++ = pbi_crc_cmd1;
  154. *pmem_buf++ = pbi_crc_cmd2;
  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. }
  165. void pbl_load_uboot(int ifd, struct image_tool_params *params)
  166. {
  167. FILE *fp_uboot;
  168. int size;
  169. /* parse the rcw.cfg file. */
  170. pbl_parser(params->imagename);
  171. /* parse the pbi.cfg file. */
  172. if (params->imagename2[0] != '\0')
  173. pbl_parser(params->imagename2);
  174. if (params->datafile) {
  175. fp_uboot = fopen(params->datafile, "r");
  176. if (fp_uboot == NULL) {
  177. printf("Error: %s open failed\n", params->datafile);
  178. exit(EXIT_FAILURE);
  179. }
  180. load_uboot(fp_uboot);
  181. fclose(fp_uboot);
  182. }
  183. add_end_cmd();
  184. lseek(ifd, 0, SEEK_SET);
  185. size = pbl_size;
  186. if (write(ifd, (const void *)&mem_buf, size) != size) {
  187. fprintf(stderr, "Write error on %s: %s\n",
  188. params->imagefile, strerror(errno));
  189. exit(EXIT_FAILURE);
  190. }
  191. }
  192. static int pblimage_check_image_types(uint8_t type)
  193. {
  194. if (type == IH_TYPE_PBLIMAGE)
  195. return EXIT_SUCCESS;
  196. else
  197. return EXIT_FAILURE;
  198. }
  199. static int pblimage_verify_header(unsigned char *ptr, int image_size,
  200. struct image_tool_params *params)
  201. {
  202. struct pbl_header *pbl_hdr = (struct pbl_header *) ptr;
  203. /* Only a few checks can be done: search for magic numbers */
  204. if (ENDIANNESS == 'l') {
  205. if (pbl_hdr->preamble != reverse_byte(RCW_PREAMBLE))
  206. return -FDT_ERR_BADSTRUCTURE;
  207. if (pbl_hdr->rcwheader != reverse_byte(RCW_HEADER))
  208. return -FDT_ERR_BADSTRUCTURE;
  209. } else {
  210. if (pbl_hdr->preamble != RCW_PREAMBLE)
  211. return -FDT_ERR_BADSTRUCTURE;
  212. if (pbl_hdr->rcwheader != RCW_HEADER)
  213. return -FDT_ERR_BADSTRUCTURE;
  214. }
  215. return 0;
  216. }
  217. static void pblimage_print_header(const void *ptr)
  218. {
  219. printf("Image Type: Freescale PBL Boot Image\n");
  220. }
  221. static void pblimage_set_header(void *ptr, struct stat *sbuf, int ifd,
  222. struct image_tool_params *params)
  223. {
  224. /*nothing need to do, pbl_load_uboot takes care of whole file. */
  225. }
  226. int pblimage_check_params(struct image_tool_params *params)
  227. {
  228. FILE *fp_uboot;
  229. int fd;
  230. struct stat st;
  231. if (!params)
  232. return EXIT_FAILURE;
  233. if (params->datafile) {
  234. fp_uboot = fopen(params->datafile, "r");
  235. if (fp_uboot == NULL) {
  236. printf("Error: %s open failed\n", params->datafile);
  237. exit(EXIT_FAILURE);
  238. }
  239. fd = fileno(fp_uboot);
  240. if (fstat(fd, &st) == -1) {
  241. printf("Error: Could not determine u-boot image size. %s\n",
  242. strerror(errno));
  243. exit(EXIT_FAILURE);
  244. }
  245. /* For the variable size, pad it to 64 byte boundary */
  246. uboot_size = roundup(st.st_size, 64);
  247. fclose(fp_uboot);
  248. }
  249. if (params->arch == IH_ARCH_ARM) {
  250. arch_flag = IH_ARCH_ARM;
  251. pbi_crc_cmd1 = 0x61;
  252. pbi_crc_cmd2 = 0;
  253. pbl_cmd_initaddr = params->addr & PBL_ADDR_24BIT_MASK;
  254. pbl_cmd_initaddr |= PBL_ACS_CONT_CMD;
  255. pbl_cmd_initaddr += uboot_size;
  256. pbl_end_cmd[0] = 0x09610000;
  257. pbl_end_cmd[1] = 0x00000000;
  258. pbl_end_cmd[2] = 0x096100c0;
  259. pbl_end_cmd[3] = 0x00000000;
  260. } else if (params->arch == IH_ARCH_PPC) {
  261. arch_flag = IH_ARCH_PPC;
  262. pbi_crc_cmd1 = 0x13;
  263. pbi_crc_cmd2 = 0x80;
  264. pbl_cmd_initaddr = 0x82000000;
  265. pbl_end_cmd[0] = 0x091380c0;
  266. pbl_end_cmd[1] = 0x00000000;
  267. pbl_end_cmd[2] = 0x091380c0;
  268. pbl_end_cmd[3] = 0x00000000;
  269. }
  270. next_pbl_cmd = pbl_cmd_initaddr;
  271. return 0;
  272. };
  273. /* pblimage parameters */
  274. U_BOOT_IMAGE_TYPE(
  275. pblimage,
  276. "Freescale PBL Boot Image support",
  277. sizeof(struct pbl_header),
  278. (void *)&pblimage_header,
  279. pblimage_check_params,
  280. pblimage_verify_header,
  281. pblimage_print_header,
  282. pblimage_set_header,
  283. NULL,
  284. pblimage_check_image_types,
  285. NULL,
  286. NULL
  287. );