pblimage.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  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. #define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
  10. #define PBL_ACS_CONT_CMD 0x81000000
  11. #define PBL_ADDR_24BIT_MASK 0x00ffffff
  12. /*
  13. * Initialize to an invalid value.
  14. */
  15. static uint32_t next_pbl_cmd = 0x82000000;
  16. /*
  17. * need to store all bytes in memory for calculating crc32, then write the
  18. * bytes to image file for PBL boot.
  19. */
  20. static unsigned char mem_buf[1000000];
  21. static unsigned char *pmem_buf = mem_buf;
  22. static int pbl_size;
  23. static char *fname = "Unknown";
  24. static int lineno = -1;
  25. static struct pbl_header pblimage_header;
  26. static int uboot_size;
  27. static int arch_flag;
  28. static uint32_t pbl_cmd_initaddr;
  29. static uint32_t pbi_crc_cmd1;
  30. static uint32_t pbi_crc_cmd2;
  31. static uint32_t pbl_end_cmd[4];
  32. static union
  33. {
  34. char c[4];
  35. unsigned char l;
  36. } endian_test = { {'l', '?', '?', 'b'} };
  37. #define ENDIANNESS ((char)endian_test.l)
  38. /*
  39. * The PBL can load up to 64 bytes at a time, so we split the U-Boot
  40. * image into 64 byte chunks. PBL needs a command for each piece, of
  41. * the form "81xxxxxx", where "xxxxxx" is the offset. Calculate the
  42. * start offset by subtracting the size of the u-boot image from the
  43. * top of the allowable 24-bit range.
  44. */
  45. static void generate_pbl_cmd(void)
  46. {
  47. uint32_t val = next_pbl_cmd;
  48. next_pbl_cmd += 0x40;
  49. int i;
  50. for (i = 3; i >= 0; i--) {
  51. *pmem_buf++ = (val >> (i * 8)) & 0xff;
  52. pbl_size++;
  53. }
  54. }
  55. static void pbl_fget(size_t size, FILE *stream)
  56. {
  57. unsigned char c = 0xff;
  58. int c_temp;
  59. while (size) {
  60. c_temp = fgetc(stream);
  61. if (c_temp != EOF)
  62. c = (unsigned char)c_temp;
  63. else if ((c_temp == EOF) && (arch_flag == IH_ARCH_ARM))
  64. c = 0xff;
  65. *pmem_buf++ = c;
  66. pbl_size++;
  67. size--;
  68. }
  69. }
  70. /* load split u-boot with PBI command 81xxxxxx. */
  71. static void load_uboot(FILE *fp_uboot)
  72. {
  73. next_pbl_cmd = pbl_cmd_initaddr - uboot_size;
  74. while (next_pbl_cmd < pbl_cmd_initaddr) {
  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 reverse_byte(uint32_t val)
  126. {
  127. uint32_t temp;
  128. unsigned char *p1;
  129. int j;
  130. temp = val;
  131. p1 = (unsigned char *)&temp;
  132. for (j = 3; j >= 0; j--)
  133. *p1++ = (val >> (j * 8)) & 0xff;
  134. return temp;
  135. }
  136. /* write end command and crc command to memory. */
  137. static void add_end_cmd(void)
  138. {
  139. uint32_t crc32_pbl;
  140. int i;
  141. unsigned char *p = (unsigned char *)&pbl_end_cmd;
  142. if (ENDIANNESS == 'l') {
  143. for (i = 0; i < 4; i++)
  144. pbl_end_cmd[i] = reverse_byte(pbl_end_cmd[i]);
  145. }
  146. for (i = 0; i < 16; i++) {
  147. *pmem_buf++ = *p++;
  148. pbl_size++;
  149. }
  150. /* Add PBI CRC command. */
  151. *pmem_buf++ = 0x08;
  152. *pmem_buf++ = pbi_crc_cmd1;
  153. *pmem_buf++ = pbi_crc_cmd2;
  154. *pmem_buf++ = 0x40;
  155. pbl_size += 4;
  156. /* calculated CRC32 and write it to memory. */
  157. crc32_pbl = pbl_crc32(0, (const char *)mem_buf, pbl_size);
  158. *pmem_buf++ = (crc32_pbl >> 24) & 0xff;
  159. *pmem_buf++ = (crc32_pbl >> 16) & 0xff;
  160. *pmem_buf++ = (crc32_pbl >> 8) & 0xff;
  161. *pmem_buf++ = (crc32_pbl) & 0xff;
  162. pbl_size += 4;
  163. }
  164. void pbl_load_uboot(int ifd, struct image_tool_params *params)
  165. {
  166. FILE *fp_uboot;
  167. int size;
  168. /* parse the rcw.cfg file. */
  169. pbl_parser(params->imagename);
  170. /* parse the pbi.cfg file. */
  171. if (params->imagename2[0] != '\0')
  172. pbl_parser(params->imagename2);
  173. if (params->datafile) {
  174. fp_uboot = fopen(params->datafile, "r");
  175. if (fp_uboot == NULL) {
  176. printf("Error: %s open failed\n", params->datafile);
  177. exit(EXIT_FAILURE);
  178. }
  179. load_uboot(fp_uboot);
  180. fclose(fp_uboot);
  181. }
  182. add_end_cmd();
  183. lseek(ifd, 0, SEEK_SET);
  184. size = pbl_size;
  185. if (write(ifd, (const void *)&mem_buf, size) != size) {
  186. fprintf(stderr, "Write error on %s: %s\n",
  187. params->imagefile, strerror(errno));
  188. exit(EXIT_FAILURE);
  189. }
  190. }
  191. static int pblimage_check_image_types(uint8_t type)
  192. {
  193. if (type == IH_TYPE_PBLIMAGE)
  194. return EXIT_SUCCESS;
  195. else
  196. return EXIT_FAILURE;
  197. }
  198. static int pblimage_verify_header(unsigned char *ptr, int image_size,
  199. struct image_tool_params *params)
  200. {
  201. struct pbl_header *pbl_hdr = (struct pbl_header *) ptr;
  202. /* Only a few checks can be done: search for magic numbers */
  203. if (ENDIANNESS == 'l') {
  204. if (pbl_hdr->preamble != reverse_byte(RCW_PREAMBLE))
  205. return -FDT_ERR_BADSTRUCTURE;
  206. if (pbl_hdr->rcwheader != reverse_byte(RCW_HEADER))
  207. return -FDT_ERR_BADSTRUCTURE;
  208. } else {
  209. if (pbl_hdr->preamble != RCW_PREAMBLE)
  210. return -FDT_ERR_BADSTRUCTURE;
  211. if (pbl_hdr->rcwheader != RCW_HEADER)
  212. return -FDT_ERR_BADSTRUCTURE;
  213. }
  214. return 0;
  215. }
  216. static void pblimage_print_header(const void *ptr)
  217. {
  218. printf("Image Type: Freescale PBL Boot Image\n");
  219. }
  220. static void pblimage_set_header(void *ptr, struct stat *sbuf, int ifd,
  221. struct image_tool_params *params)
  222. {
  223. /*nothing need to do, pbl_load_uboot takes care of whole file. */
  224. }
  225. int pblimage_check_params(struct image_tool_params *params)
  226. {
  227. FILE *fp_uboot;
  228. int fd;
  229. struct stat st;
  230. if (!params)
  231. return EXIT_FAILURE;
  232. if (params->datafile) {
  233. fp_uboot = fopen(params->datafile, "r");
  234. if (fp_uboot == NULL) {
  235. printf("Error: %s open failed\n", params->datafile);
  236. exit(EXIT_FAILURE);
  237. }
  238. fd = fileno(fp_uboot);
  239. if (fstat(fd, &st) == -1) {
  240. printf("Error: Could not determine u-boot image size. %s\n",
  241. strerror(errno));
  242. exit(EXIT_FAILURE);
  243. }
  244. /* For the variable size, pad it to 64 byte boundary */
  245. uboot_size = roundup(st.st_size, 64);
  246. fclose(fp_uboot);
  247. }
  248. if (params->arch == IH_ARCH_ARM) {
  249. arch_flag = IH_ARCH_ARM;
  250. pbi_crc_cmd1 = 0x61;
  251. pbi_crc_cmd2 = 0;
  252. pbl_cmd_initaddr = params->addr & PBL_ADDR_24BIT_MASK;
  253. pbl_cmd_initaddr |= PBL_ACS_CONT_CMD;
  254. pbl_cmd_initaddr += uboot_size;
  255. pbl_end_cmd[0] = 0x09610000;
  256. pbl_end_cmd[1] = 0x00000000;
  257. pbl_end_cmd[2] = 0x096100c0;
  258. pbl_end_cmd[3] = 0x00000000;
  259. } else if (params->arch == IH_ARCH_PPC) {
  260. arch_flag = IH_ARCH_PPC;
  261. pbi_crc_cmd1 = 0x13;
  262. pbi_crc_cmd2 = 0x80;
  263. pbl_cmd_initaddr = 0x82000000;
  264. pbl_end_cmd[0] = 0x091380c0;
  265. pbl_end_cmd[1] = 0x00000000;
  266. pbl_end_cmd[2] = 0x091380c0;
  267. pbl_end_cmd[3] = 0x00000000;
  268. }
  269. next_pbl_cmd = pbl_cmd_initaddr;
  270. return 0;
  271. };
  272. /* pblimage parameters */
  273. U_BOOT_IMAGE_TYPE(
  274. pblimage,
  275. "Freescale PBL Boot Image support",
  276. sizeof(struct pbl_header),
  277. (void *)&pblimage_header,
  278. pblimage_check_params,
  279. pblimage_verify_header,
  280. pblimage_print_header,
  281. pblimage_set_header,
  282. NULL,
  283. pblimage_check_image_types,
  284. NULL,
  285. NULL
  286. );