imx8image.c 26 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright 2018 NXP
  4. *
  5. * Peng Fan <peng.fan@nxp.com>
  6. */
  7. #include "imx8image.h"
  8. #include <image.h>
  9. static int p_idx;
  10. static int sector_size;
  11. static soc_type_t soc;
  12. static int container = -1;
  13. static int32_t core_type = CFG_CORE_INVALID;
  14. static bool emmc_fastboot;
  15. static image_t param_stack[IMG_STACK_SIZE];
  16. static uint8_t fuse_version;
  17. static uint16_t sw_version;
  18. static uint32_t custom_partition;
  19. static uint32_t scfw_flags;
  20. int imx8image_check_params(struct image_tool_params *params)
  21. {
  22. return 0;
  23. }
  24. static void imx8image_set_header(void *ptr, struct stat *sbuf, int ifd,
  25. struct image_tool_params *params)
  26. {
  27. }
  28. static void imx8image_print_header(const void *ptr, struct image_tool_params *params)
  29. {
  30. }
  31. static int imx8image_check_image_types(uint8_t type)
  32. {
  33. return (type == IH_TYPE_IMX8IMAGE) ? EXIT_SUCCESS : EXIT_FAILURE;
  34. }
  35. static table_entry_t imx8image_cmds[] = {
  36. {CMD_BOOT_FROM, "BOOT_FROM", "boot command", },
  37. {CMD_FUSE_VERSION, "FUSE_VERSION", "fuse version", },
  38. {CMD_SW_VERSION, "SW_VERSION", "sw version", },
  39. {CMD_MSG_BLOCK, "MSG_BLOCK", "msg block", },
  40. {CMD_FILEOFF, "FILEOFF", "fileoff", },
  41. {CMD_FLAG, "FLAG", "flag", },
  42. {CMD_APPEND, "APPEND", "append a container", },
  43. {CMD_PARTITION, "PARTITION", "new partition", },
  44. {CMD_SOC_TYPE, "SOC_TYPE", "soc type", },
  45. {CMD_CONTAINER, "CONTAINER", "new container", },
  46. {CMD_IMAGE, "IMAGE", "new image", },
  47. {CMD_DATA, "DATA", "new data", },
  48. {-1, "", "", },
  49. };
  50. static table_entry_t imx8image_core_entries[] = {
  51. {CFG_SCU, "SCU", "scu core", },
  52. {CFG_M40, "M40", "M4 core 0", },
  53. {CFG_M41, "M41", "M4 core 1", },
  54. {CFG_A35, "A35", "A35 core", },
  55. {CFG_A55, "A55", "A55 core", },
  56. {CFG_A53, "A53", "A53 core", },
  57. {CFG_A72, "A72", "A72 core", },
  58. {-1, "", "", },
  59. };
  60. static table_entry_t imx8image_sector_size[] = {
  61. {0x400, "sd", "sd/emmc",},
  62. {0x400, "emmc_fastboot", "emmc fastboot",},
  63. {0x400, "fspi", "flexspi", },
  64. {0x1000, "nand_4k", "nand 4K", },
  65. {0x2000, "nand_8k", "nand 8K", },
  66. {0x4000, "nand_16k", "nand 16K", },
  67. {-1, "", "Invalid", },
  68. };
  69. static void parse_cfg_cmd(image_t *param_stack, int32_t cmd, char *token,
  70. char *name, int lineno)
  71. {
  72. switch (cmd) {
  73. case CMD_BOOT_FROM:
  74. sector_size = get_table_entry_id(imx8image_sector_size,
  75. "imximage boot option",
  76. token);
  77. if (!strncmp("emmc_fastboot", token, 13))
  78. emmc_fastboot = true;
  79. break;
  80. case CMD_FUSE_VERSION:
  81. fuse_version = (uint8_t)(strtoll(token, NULL, 0) & 0xFF);
  82. break;
  83. case CMD_SW_VERSION:
  84. sw_version = (uint8_t)(strtoll(token, NULL, 0) & 0xFFFF);
  85. break;
  86. case CMD_FILEOFF:
  87. param_stack[p_idx].option = FILEOFF;
  88. param_stack[p_idx++].dst = (uint32_t)strtoll(token, NULL, 0);
  89. break;
  90. case CMD_MSG_BLOCK:
  91. param_stack[p_idx].option = MSG_BLOCK;
  92. param_stack[p_idx].filename = token;
  93. break;
  94. case CMD_FLAG:
  95. param_stack[p_idx].option = FLAG;
  96. param_stack[p_idx++].entry = (uint32_t)strtoll(token, NULL, 0);
  97. break;
  98. case CMD_APPEND:
  99. param_stack[p_idx].option = APPEND;
  100. param_stack[p_idx++].filename = token;
  101. break;
  102. case CMD_PARTITION:
  103. param_stack[p_idx].option = PARTITION;
  104. param_stack[p_idx++].entry = (uint32_t)strtoll(token, NULL, 0);
  105. break;
  106. case CMD_SOC_TYPE:
  107. if (!strncmp(token, "IMX8QX", 6)) {
  108. soc = QX;
  109. } else if (!strncmp(token, "IMX8QM", 6)) {
  110. soc = QM;
  111. } else if (!strncmp(token, "ULP", 3)) {
  112. soc = IMX9;
  113. } else if (!strncmp(token, "IMX9", 4)) {
  114. soc = IMX9;
  115. } else {
  116. fprintf(stderr, "Unknown CMD_SOC_TYPE");
  117. exit(EXIT_FAILURE);
  118. }
  119. break;
  120. case CMD_IMAGE:
  121. case CMD_DATA:
  122. core_type = get_table_entry_id(imx8image_core_entries,
  123. "imx8image core entries",
  124. token);
  125. if (core_type < 0) {
  126. fprintf(stderr, "Wrong IMAGE core_type %s\n", token);
  127. exit(EXIT_FAILURE);
  128. }
  129. break;
  130. default:
  131. break;
  132. }
  133. }
  134. static void parse_cfg_fld(image_t *param_stack, int32_t *cmd, char *token,
  135. char *name, int lineno, int fld)
  136. {
  137. switch (fld) {
  138. case CFG_COMMAND:
  139. *cmd = get_table_entry_id(imx8image_cmds, "imx8image cmds",
  140. token);
  141. if (*cmd < 0) {
  142. fprintf(stderr, "Error: %s[%d] - Invalid command (%s)\n", name, lineno, token);
  143. exit(EXIT_FAILURE);
  144. }
  145. if (*cmd == CMD_CONTAINER) {
  146. fprintf(stdout, "New Container: \t%d\n", ++container);
  147. param_stack[p_idx++].option = NEW_CONTAINER;
  148. }
  149. break;
  150. case CFG_CORE_TYPE:
  151. parse_cfg_cmd(param_stack, *cmd, token, name, lineno);
  152. break;
  153. case CFG_IMAGE_NAME:
  154. if (*cmd == CMD_MSG_BLOCK) {
  155. if (!strncmp(token, "fuse", 4)) {
  156. param_stack[p_idx].ext = SC_R_OTP;
  157. } else if (!strncmp(token, "debug", 5)) {
  158. param_stack[p_idx].ext = SC_R_DEBUG;
  159. } else if (!strncmp(token, "field", 5)) {
  160. param_stack[p_idx].ext = SC_R_ROM_0;
  161. } else {
  162. fprintf(stderr, "MSG type not found %s\n", token);
  163. exit(EXIT_FAILURE);
  164. }
  165. break;
  166. }
  167. switch (core_type) {
  168. case CFG_SCU:
  169. param_stack[p_idx].option = SCFW;
  170. param_stack[p_idx++].filename = token;
  171. break;
  172. case CFG_M40:
  173. param_stack[p_idx].option = M40;
  174. param_stack[p_idx].ext = 0;
  175. param_stack[p_idx].filename = token;
  176. break;
  177. case CFG_M41:
  178. param_stack[p_idx].option = M41;
  179. param_stack[p_idx].ext = 1;
  180. param_stack[p_idx].filename = token;
  181. break;
  182. case CFG_A35:
  183. case CFG_A55:
  184. param_stack[p_idx].ext = CORE_CA35;
  185. param_stack[p_idx].option =
  186. (*cmd == CMD_DATA) ? DATA : AP;
  187. param_stack[p_idx].filename = token;
  188. break;
  189. case CFG_A53:
  190. param_stack[p_idx].ext = CORE_CA53;
  191. param_stack[p_idx].option =
  192. (*cmd == CMD_DATA) ? DATA : AP;
  193. param_stack[p_idx].filename = token;
  194. break;
  195. case CFG_A72:
  196. param_stack[p_idx].ext = CORE_CA72;
  197. param_stack[p_idx].option =
  198. (*cmd == CMD_DATA) ? DATA : AP;
  199. param_stack[p_idx].filename = token;
  200. break;
  201. }
  202. break;
  203. case CFG_LOAD_ADDR:
  204. if (*cmd == CMD_MSG_BLOCK) {
  205. param_stack[p_idx++].entry =
  206. (uint32_t)strtoll(token, NULL, 0);
  207. break;
  208. }
  209. switch (core_type) {
  210. case CFG_SCU:
  211. break;
  212. case CFG_M40:
  213. case CFG_M41:
  214. case CFG_A35:
  215. case CFG_A53:
  216. case CFG_A55:
  217. case CFG_A72:
  218. param_stack[p_idx++].entry =
  219. (uint32_t)strtoll(token, NULL, 0);
  220. break;
  221. }
  222. default:
  223. break;
  224. }
  225. }
  226. static uint32_t parse_cfg_file(image_t *param_stack, char *name)
  227. {
  228. FILE *fd = NULL;
  229. char *line = NULL;
  230. char *token, *saveptr1, *saveptr2;
  231. int lineno = 0;
  232. int fld;
  233. size_t len;
  234. int32_t cmd;
  235. fd = fopen(name, "r");
  236. if (fd == 0) {
  237. fprintf(stderr, "Error: %s - Can't open cfg file\n", name);
  238. exit(EXIT_FAILURE);
  239. }
  240. /*
  241. * Very simple parsing, line starting with # are comments
  242. * and are dropped
  243. */
  244. while ((getline(&line, &len, fd)) > 0) {
  245. lineno++;
  246. token = strtok_r(line, "\r\n", &saveptr1);
  247. if (!token)
  248. continue;
  249. /* Check inside the single line */
  250. for (fld = CFG_COMMAND, cmd = CFG_INVALID,
  251. line = token; ; line = NULL, fld++) {
  252. token = strtok_r(line, " \t", &saveptr2);
  253. if (!token)
  254. break;
  255. /* Drop all text starting with '#' as comments */
  256. if (token[0] == '#')
  257. break;
  258. parse_cfg_fld(param_stack, &cmd, token, name, lineno,
  259. fld);
  260. }
  261. }
  262. fclose(fd);
  263. return 0;
  264. }
  265. static void check_file(struct stat *sbuf, char *filename)
  266. {
  267. int tmp_fd = open(filename, O_RDONLY | O_BINARY);
  268. if (tmp_fd < 0) {
  269. fprintf(stderr, "%s: Can't open: %s\n",
  270. filename, strerror(errno));
  271. exit(EXIT_FAILURE);
  272. }
  273. if (fstat(tmp_fd, sbuf) < 0) {
  274. fprintf(stderr, "%s: Can't stat: %s\n",
  275. filename, strerror(errno));
  276. exit(EXIT_FAILURE);
  277. }
  278. close(tmp_fd);
  279. }
  280. static void copy_file_aligned(int ifd, const char *datafile, int offset,
  281. int align)
  282. {
  283. int dfd;
  284. struct stat sbuf;
  285. unsigned char *ptr;
  286. uint8_t zeros[0x4000];
  287. int size;
  288. int ret;
  289. if (align > 0x4000) {
  290. fprintf(stderr, "Wrong alignment requested %d\n", align);
  291. exit(EXIT_FAILURE);
  292. }
  293. memset(zeros, 0, sizeof(zeros));
  294. dfd = open(datafile, O_RDONLY | O_BINARY);
  295. if (dfd < 0) {
  296. fprintf(stderr, "Can't open %s: %s\n",
  297. datafile, strerror(errno));
  298. exit(EXIT_FAILURE);
  299. }
  300. if (fstat(dfd, &sbuf) < 0) {
  301. fprintf(stderr, "Can't stat %s: %s\n",
  302. datafile, strerror(errno));
  303. exit(EXIT_FAILURE);
  304. }
  305. if (sbuf.st_size == 0)
  306. goto close;
  307. ptr = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, dfd, 0);
  308. if (ptr == MAP_FAILED) {
  309. fprintf(stderr, "Can't read %s: %s\n",
  310. datafile, strerror(errno));
  311. exit(EXIT_FAILURE);
  312. }
  313. size = sbuf.st_size;
  314. ret = lseek(ifd, offset, SEEK_SET);
  315. if (ret < 0) {
  316. fprintf(stderr, "%s: lseek error %s\n",
  317. __func__, strerror(errno));
  318. exit(EXIT_FAILURE);
  319. }
  320. if (write(ifd, ptr, size) != size) {
  321. fprintf(stderr, "Write error %s\n", strerror(errno));
  322. exit(EXIT_FAILURE);
  323. }
  324. align = ALIGN(size, align) - size;
  325. if (write(ifd, (char *)&zeros, align) != align) {
  326. fprintf(stderr, "Write error: %s\n", strerror(errno));
  327. exit(EXIT_FAILURE);
  328. }
  329. munmap((void *)ptr, sbuf.st_size);
  330. close:
  331. close(dfd);
  332. }
  333. static void copy_file (int ifd, const char *datafile, int pad, int offset)
  334. {
  335. int dfd;
  336. struct stat sbuf;
  337. unsigned char *ptr;
  338. int tail;
  339. uint64_t zero = 0;
  340. uint8_t zeros[4096];
  341. int size, ret;
  342. memset(zeros, 0, sizeof(zeros));
  343. dfd = open(datafile, O_RDONLY | O_BINARY);
  344. if (dfd < 0) {
  345. fprintf(stderr, "Can't open %s: %s\n",
  346. datafile, strerror(errno));
  347. exit(EXIT_FAILURE);
  348. }
  349. if (fstat(dfd, &sbuf) < 0) {
  350. fprintf(stderr, "Can't stat %s: %s\n",
  351. datafile, strerror(errno));
  352. exit(EXIT_FAILURE);
  353. }
  354. if (sbuf.st_size == 0)
  355. goto close;
  356. ptr = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, dfd, 0);
  357. if (ptr == MAP_FAILED) {
  358. fprintf(stderr, "Can't read %s: %s\n",
  359. datafile, strerror(errno));
  360. exit(EXIT_FAILURE);
  361. }
  362. size = sbuf.st_size;
  363. ret = lseek(ifd, offset, SEEK_SET);
  364. if (ret < 0) {
  365. fprintf(stderr, "%s: lseek error %s\n",
  366. __func__, strerror(errno));
  367. exit(EXIT_FAILURE);
  368. }
  369. if (write(ifd, ptr, size) != size) {
  370. fprintf(stderr, "Write error %s\n",
  371. strerror(errno));
  372. exit(EXIT_FAILURE);
  373. }
  374. tail = size % 4;
  375. pad = pad - size;
  376. if (pad == 1 && tail != 0) {
  377. if (write(ifd, (char *)&zero, 4 - tail) != 4 - tail) {
  378. fprintf(stderr, "Write error on %s\n",
  379. strerror(errno));
  380. exit(EXIT_FAILURE);
  381. }
  382. } else if (pad > 1) {
  383. while (pad > 0) {
  384. int todo = sizeof(zeros);
  385. if (todo > pad)
  386. todo = pad;
  387. if (write(ifd, (char *)&zeros, todo) != todo) {
  388. fprintf(stderr, "Write error: %s\n",
  389. strerror(errno));
  390. exit(EXIT_FAILURE);
  391. }
  392. pad -= todo;
  393. }
  394. }
  395. munmap((void *)ptr, sbuf.st_size);
  396. close:
  397. close(dfd);
  398. }
  399. uint64_t read_dcd_offset(char *filename)
  400. {
  401. int dfd;
  402. struct stat sbuf;
  403. uint8_t *ptr;
  404. uint64_t offset = 0;
  405. dfd = open(filename, O_RDONLY | O_BINARY);
  406. if (dfd < 0) {
  407. fprintf(stderr, "Can't open %s: %s\n", filename, strerror(errno));
  408. exit(EXIT_FAILURE);
  409. }
  410. if (fstat(dfd, &sbuf) < 0) {
  411. fprintf(stderr, "Can't stat %s: %s\n", filename, strerror(errno));
  412. exit(EXIT_FAILURE);
  413. }
  414. ptr = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, dfd, 0);
  415. if (ptr == MAP_FAILED) {
  416. fprintf(stderr, "Can't read %s: %s\n", filename, strerror(errno));
  417. exit(EXIT_FAILURE);
  418. }
  419. offset = *(uint32_t *)(ptr + DCD_ENTRY_ADDR_IN_SCFW);
  420. munmap((void *)ptr, sbuf.st_size);
  421. close(dfd);
  422. return offset;
  423. }
  424. static void set_image_hash(boot_img_t *img, char *filename, uint32_t hash_type)
  425. {
  426. FILE *fp = NULL;
  427. char sha_command[512];
  428. char hash[2 * HASH_MAX_LEN + 1];
  429. int i, ret;
  430. if (img->size == 0)
  431. sprintf(sha_command, "sha%dsum /dev/null", hash_type);
  432. else
  433. sprintf(sha_command, "dd if=/dev/zero of=tmp_pad bs=%d count=1;\
  434. dd if=\'%s\' of=tmp_pad conv=notrunc;\
  435. sha%dsum tmp_pad; rm -f tmp_pad",
  436. img->size, filename, hash_type);
  437. switch (hash_type) {
  438. case HASH_TYPE_SHA_256:
  439. img->hab_flags |= IMG_FLAG_HASH_SHA256;
  440. break;
  441. case HASH_TYPE_SHA_384:
  442. img->hab_flags |= IMG_FLAG_HASH_SHA384;
  443. break;
  444. case HASH_TYPE_SHA_512:
  445. img->hab_flags |= IMG_FLAG_HASH_SHA512;
  446. break;
  447. default:
  448. fprintf(stderr, "Wrong hash type selected (%d) !!!\n\n",
  449. hash_type);
  450. exit(EXIT_FAILURE);
  451. break;
  452. }
  453. memset(img->hash, 0, HASH_MAX_LEN);
  454. fp = popen(sha_command, "r");
  455. if (!fp) {
  456. fprintf(stderr, "Failed to run command hash\n");
  457. exit(EXIT_FAILURE);
  458. }
  459. if (!fgets(hash, hash_type / 4 + 1, fp)) {
  460. fprintf(stderr, "Failed to hash file: %s\n", filename);
  461. exit(EXIT_FAILURE);
  462. }
  463. for (i = 0; i < strlen(hash) / 2; i++) {
  464. ret = sscanf(hash + 2 * i, "%02hhx", &img->hash[i]);
  465. if (ret < 0) {
  466. fprintf(stderr, "Failed sscanf hash: %d\n", ret);
  467. exit(EXIT_FAILURE);
  468. }
  469. }
  470. pclose(fp);
  471. }
  472. static void set_image_array_entry(flash_header_v3_t *container,
  473. soc_type_t soc, const image_t *image_stack,
  474. uint32_t offset, uint32_t size,
  475. char *tmp_filename, bool dcd_skip)
  476. {
  477. uint64_t entry = image_stack->entry;
  478. uint64_t core = image_stack->ext;
  479. uint32_t meta;
  480. char *tmp_name = "";
  481. option_type_t type = image_stack->option;
  482. boot_img_t *img = &container->img[container->num_images];
  483. img->offset = offset; /* Is re-adjusted later */
  484. img->size = size;
  485. set_image_hash(img, tmp_filename, IMAGE_HASH_ALGO_DEFAULT);
  486. switch (type) {
  487. case SECO:
  488. img->hab_flags |= IMG_TYPE_SECO;
  489. img->hab_flags |= CORE_SECO << BOOT_IMG_FLAGS_CORE_SHIFT;
  490. tmp_name = "SECO";
  491. img->dst = 0x20C00000;
  492. img->entry = 0x20000000;
  493. break;
  494. case SENTINEL:
  495. if (container->num_images > 0) {
  496. fprintf(stderr, "Error: SENTINEL container only allows 1 image\n");
  497. return;
  498. }
  499. img->hab_flags |= IMG_TYPE_SENTINEL;
  500. img->hab_flags |= CORE_ULP_SENTINEL << BOOT_IMG_FLAGS_CORE_SHIFT;
  501. tmp_name = "SENTINEL";
  502. img->dst = 0xe4000000; /* S400 IRAM base */
  503. img->entry = 0xe4000000;
  504. break;
  505. case AP:
  506. if (soc == QX && core == CORE_CA35) {
  507. meta = IMAGE_A35_DEFAULT_META(custom_partition);
  508. } else if (soc == QM && core == CORE_CA53) {
  509. meta = IMAGE_A53_DEFAULT_META(custom_partition);
  510. } else if (soc == QM && core == CORE_CA72) {
  511. meta = IMAGE_A72_DEFAULT_META(custom_partition);
  512. } else if (((soc == ULP) || (soc == IMX9)) && core == CORE_CA35) {
  513. meta = 0;
  514. } else {
  515. fprintf(stderr,
  516. "Error: invalid AP core id: %" PRIu64 "\n",
  517. core);
  518. exit(EXIT_FAILURE);
  519. }
  520. img->hab_flags |= IMG_TYPE_EXEC;
  521. if ((soc == ULP) || (soc == IMX9))
  522. img->hab_flags |= CORE_ULP_CA35 << BOOT_IMG_FLAGS_CORE_SHIFT;
  523. else
  524. img->hab_flags |= CORE_CA53 << BOOT_IMG_FLAGS_CORE_SHIFT; /* On B0, only core id = 4 is valid */
  525. tmp_name = "AP";
  526. img->dst = entry;
  527. img->entry = entry;
  528. img->meta = meta;
  529. custom_partition = 0;
  530. break;
  531. case M40:
  532. case M41:
  533. if ((soc == ULP) || (soc == IMX9)) {
  534. core = CORE_ULP_CM33;
  535. meta = 0;
  536. } else {
  537. if (core == 0) {
  538. core = CORE_CM4_0;
  539. meta = IMAGE_M4_0_DEFAULT_META(custom_partition);
  540. } else if (core == 1) {
  541. core = CORE_CM4_1;
  542. meta = IMAGE_M4_1_DEFAULT_META(custom_partition);
  543. } else {
  544. fprintf(stderr,
  545. "Error: invalid m4 core id: %" PRIu64 "\n",
  546. core);
  547. exit(EXIT_FAILURE);
  548. }
  549. }
  550. img->hab_flags |= IMG_TYPE_EXEC;
  551. img->hab_flags |= core << BOOT_IMG_FLAGS_CORE_SHIFT;
  552. tmp_name = "M4";
  553. if ((entry & 0x7) != 0) {
  554. fprintf(stderr, "\n\nWarning: M4 Destination address is not 8 byte aligned\n\n");
  555. exit(EXIT_FAILURE);
  556. }
  557. img->dst = entry;
  558. img->entry = entry;
  559. img->meta = meta;
  560. custom_partition = 0;
  561. break;
  562. case DATA:
  563. img->hab_flags |= IMG_TYPE_DATA;
  564. if ((soc == ULP) || (soc == IMX9)) {
  565. if (core == CORE_CM4_0)
  566. img->hab_flags |= CORE_ULP_CM33 << BOOT_IMG_FLAGS_CORE_SHIFT;
  567. else
  568. img->hab_flags |= CORE_ULP_CA35 << BOOT_IMG_FLAGS_CORE_SHIFT;
  569. } else {
  570. img->hab_flags |= CORE_CA35 << BOOT_IMG_FLAGS_CORE_SHIFT;
  571. }
  572. tmp_name = "DATA";
  573. img->dst = entry;
  574. break;
  575. case MSG_BLOCK:
  576. img->hab_flags |= IMG_TYPE_DATA;
  577. img->hab_flags |= CORE_CA35 << BOOT_IMG_FLAGS_CORE_SHIFT;
  578. img->meta = core << BOOT_IMG_META_MU_RID_SHIFT;
  579. tmp_name = "MSG_BLOCK";
  580. img->dst = entry;
  581. break;
  582. case SCFW:
  583. img->hab_flags |= scfw_flags & 0xFFFF0000;
  584. img->hab_flags |= IMG_TYPE_EXEC;
  585. img->hab_flags |= CORE_SC << BOOT_IMG_FLAGS_CORE_SHIFT;
  586. tmp_name = "SCFW";
  587. img->dst = 0x1FFE0000;
  588. img->entry = 0x1FFE0000;
  589. /* Lets add the DCD now */
  590. if (!dcd_skip) {
  591. container->num_images++;
  592. img = &container->img[container->num_images];
  593. img->hab_flags |= IMG_TYPE_DCD_DDR;
  594. img->hab_flags |= CORE_SC << BOOT_IMG_FLAGS_CORE_SHIFT;
  595. set_image_hash(img, "/dev/null",
  596. IMAGE_HASH_ALGO_DEFAULT);
  597. img->offset = offset + img->size;
  598. img->entry = read_dcd_offset(tmp_filename);
  599. img->dst = img->entry - 1;
  600. }
  601. break;
  602. case UPOWER:
  603. if (soc == ULP) {
  604. img->hab_flags |= IMG_TYPE_EXEC;
  605. img->hab_flags |= CORE_ULP_UPOWER << BOOT_IMG_FLAGS_CORE_SHIFT;
  606. tmp_name = "UPOWER";
  607. img->dst = 0x28300200; /* UPOWER code RAM */
  608. img->entry = 0x28300200;
  609. }
  610. break;
  611. default:
  612. fprintf(stderr, "unrecognized image type (%d)\n", type);
  613. exit(EXIT_FAILURE);
  614. }
  615. fprintf(stdout, "%s file_offset = 0x%x size = 0x%x\n", tmp_name, offset, size);
  616. container->num_images++;
  617. }
  618. void set_container(flash_header_v3_t *container, uint16_t sw_version,
  619. uint32_t alignment, uint32_t flags, uint16_t fuse_version)
  620. {
  621. container->sig_blk_hdr.tag = 0x90;
  622. container->sig_blk_hdr.length = sizeof(sig_blk_hdr_t);
  623. container->sw_version = sw_version;
  624. container->padding = alignment;
  625. container->fuse_version = fuse_version;
  626. container->flags = flags;
  627. fprintf(stdout, "container flags: 0x%x\n", container->flags);
  628. }
  629. static int get_container_image_start_pos(image_t *image_stack, uint32_t align)
  630. {
  631. image_t *img_sp = image_stack;
  632. /*8K total container header*/
  633. int file_off = CONTAINER_IMAGE_ARRAY_START_OFFSET;
  634. FILE *fd = NULL;
  635. flash_header_v3_t header;
  636. int ret;
  637. while (img_sp->option != NO_IMG) {
  638. if (img_sp->option == APPEND) {
  639. fd = fopen(img_sp->filename, "r");
  640. if (!fd) {
  641. fprintf(stderr, "Fail open first container file %s\n", img_sp->filename);
  642. exit(EXIT_FAILURE);
  643. }
  644. ret = fread(&header, sizeof(header), 1, fd);
  645. if (ret != 1) {
  646. printf("Failure Read header %d\n", ret);
  647. exit(EXIT_FAILURE);
  648. }
  649. fclose(fd);
  650. if (header.tag != IVT_HEADER_TAG_B0) {
  651. fprintf(stderr, "header tag mismatched \n");
  652. exit(EXIT_FAILURE);
  653. } else {
  654. file_off +=
  655. header.img[header.num_images - 1].size;
  656. file_off = ALIGN(file_off, align);
  657. }
  658. }
  659. img_sp++;
  660. }
  661. return file_off;
  662. }
  663. static void set_imx_hdr_v3(imx_header_v3_t *imxhdr, uint32_t cont_id)
  664. {
  665. flash_header_v3_t *fhdr_v3 = &imxhdr->fhdr[cont_id];
  666. /* Set magic number, Only >= B0 supported */
  667. fhdr_v3->tag = IVT_HEADER_TAG_B0;
  668. fhdr_v3->version = IVT_VERSION_B0;
  669. }
  670. static uint8_t *flatten_container_header(imx_header_v3_t *imx_header,
  671. uint8_t containers_count,
  672. uint32_t *size_out,
  673. uint32_t file_offset)
  674. {
  675. uint8_t *flat = NULL;
  676. uint8_t *ptr = NULL;
  677. uint16_t size = 0;
  678. int i, j;
  679. /* Compute size of all container headers */
  680. for (i = 0; i < containers_count; i++) {
  681. flash_header_v3_t *container = &imx_header->fhdr[i];
  682. container->sig_blk_offset = HEADER_IMG_ARRAY_OFFSET +
  683. container->num_images * IMG_ARRAY_ENTRY_SIZE;
  684. container->length = HEADER_IMG_ARRAY_OFFSET +
  685. (IMG_ARRAY_ENTRY_SIZE * container->num_images) +
  686. sizeof(sig_blk_hdr_t);
  687. /* Print info needed by CST to sign the container header */
  688. fprintf(stdout, "CST: CONTAINER %d offset: 0x%x\n",
  689. i, file_offset + size);
  690. fprintf(stdout, "CST: CONTAINER %d: Signature Block: offset is at 0x%x\n", i,
  691. file_offset + size + container->length -
  692. SIGNATURE_BLOCK_HEADER_LENGTH);
  693. size += ALIGN(container->length, container->padding);
  694. }
  695. flat = calloc(size, sizeof(uint8_t));
  696. if (!flat) {
  697. fprintf(stderr, "Failed to allocate memory (%d)\n", size);
  698. exit(EXIT_FAILURE);
  699. }
  700. ptr = flat;
  701. *size_out = size;
  702. for (i = 0; i < containers_count; i++) {
  703. flash_header_v3_t *container = &imx_header->fhdr[i];
  704. uint32_t container_start_offset = ptr - flat;
  705. /* Append container header */
  706. append(ptr, container, HEADER_IMG_ARRAY_OFFSET);
  707. /* Adjust images offset to start from container headers start */
  708. for (j = 0; j < container->num_images; j++) {
  709. container->img[j].offset -=
  710. container_start_offset + file_offset;
  711. }
  712. /* Append each image array entry */
  713. for (j = 0; j < container->num_images; j++)
  714. append(ptr, &container->img[j], sizeof(boot_img_t));
  715. append(ptr, &container->sig_blk_hdr, sizeof(sig_blk_hdr_t));
  716. /* Padding for container (if necessary) */
  717. ptr += ALIGN(container->length, container->padding) -
  718. container->length;
  719. }
  720. return flat;
  721. }
  722. static int build_container(soc_type_t soc, uint32_t sector_size,
  723. bool emmc_fastboot, image_t *image_stack,
  724. bool dcd_skip, uint8_t fuse_version,
  725. uint16_t sw_version, int ofd)
  726. {
  727. static imx_header_v3_t imx_header;
  728. image_t *img_sp = image_stack;
  729. int file_off;
  730. uint8_t *tmp;
  731. struct stat sbuf;
  732. char *tmp_filename = NULL;
  733. uint32_t size = 0;
  734. uint32_t file_padding = 0;
  735. int ret;
  736. int container = -1;
  737. memset((char *)&imx_header, 0, sizeof(imx_header_v3_t));
  738. if (!image_stack) {
  739. fprintf(stderr, "Empty image stack ");
  740. exit(EXIT_FAILURE);
  741. }
  742. if (soc == QX)
  743. fprintf(stdout, "Platform:\ti.MX8QXP B0\n");
  744. else if (soc == QM)
  745. fprintf(stdout, "Platform:\ti.MX8QM B0\n");
  746. else if (soc == ULP)
  747. fprintf(stdout, "Platform:\ti.MX8ULP A0\n");
  748. else if (soc == IMX9)
  749. fprintf(stdout, "Platform:\ti.MX9\n");
  750. set_imx_hdr_v3(&imx_header, 0);
  751. set_imx_hdr_v3(&imx_header, 1);
  752. file_off = get_container_image_start_pos(image_stack, sector_size);
  753. fprintf(stdout, "container image offset (aligned):%x\n", file_off);
  754. /* step through image stack and generate the header */
  755. img_sp = image_stack;
  756. /* stop once we reach null terminator */
  757. while (img_sp->option != NO_IMG) {
  758. switch (img_sp->option) {
  759. case AP:
  760. case M40:
  761. case M41:
  762. case SCFW:
  763. case DATA:
  764. case UPOWER:
  765. case MSG_BLOCK:
  766. if (container < 0) {
  767. fprintf(stderr, "No container found\n");
  768. exit(EXIT_FAILURE);
  769. }
  770. check_file(&sbuf, img_sp->filename);
  771. tmp_filename = img_sp->filename;
  772. set_image_array_entry(&imx_header.fhdr[container],
  773. soc, img_sp, file_off,
  774. ALIGN(sbuf.st_size, sector_size),
  775. tmp_filename, dcd_skip);
  776. img_sp->src = file_off;
  777. file_off += ALIGN(sbuf.st_size, sector_size);
  778. break;
  779. case SECO:
  780. case SENTINEL:
  781. if (container < 0) {
  782. fprintf(stderr, "No container found\n");
  783. exit(EXIT_FAILURE);
  784. }
  785. check_file(&sbuf, img_sp->filename);
  786. tmp_filename = img_sp->filename;
  787. set_image_array_entry(&imx_header.fhdr[container],
  788. soc,
  789. img_sp,
  790. file_off,
  791. sbuf.st_size,
  792. tmp_filename, dcd_skip);
  793. img_sp->src = file_off;
  794. file_off += sbuf.st_size;
  795. break;
  796. case NEW_CONTAINER:
  797. container++;
  798. set_container(&imx_header.fhdr[container], sw_version,
  799. CONTAINER_ALIGNMENT,
  800. CONTAINER_FLAGS_DEFAULT,
  801. fuse_version);
  802. scfw_flags = 0;
  803. break;
  804. case APPEND:
  805. /*
  806. * nothing to do here, the container is appended
  807. * in the output
  808. */
  809. break;
  810. case FLAG:
  811. /*
  812. * override the flags for scfw in current container
  813. * mask off bottom 16 bits.
  814. */
  815. scfw_flags = img_sp->entry & 0xFFFF0000;
  816. break;
  817. case FILEOFF:
  818. if (file_off > img_sp->dst) {
  819. fprintf(stderr, "FILEOFF address less than current file offset!!!\n");
  820. exit(EXIT_FAILURE);
  821. }
  822. if (img_sp->dst != ALIGN(img_sp->dst, sector_size)) {
  823. fprintf(stderr, "FILEOFF address is not aligned to sector size!!!\n");
  824. exit(EXIT_FAILURE);
  825. }
  826. file_off = img_sp->dst;
  827. break;
  828. case PARTITION:
  829. /*
  830. * keep custom partition until next executable image
  831. * use a global var for default behaviour
  832. */
  833. custom_partition = img_sp->entry;
  834. break;
  835. default:
  836. fprintf(stderr, "unrecognized option in input stack (%d)\n", img_sp->option);
  837. exit(EXIT_FAILURE);
  838. }
  839. img_sp++; /* advance index */
  840. }
  841. /* Append container (if specified) */
  842. img_sp = image_stack;
  843. do {
  844. if (img_sp->option == APPEND) {
  845. copy_file(ofd, img_sp->filename, 0, 0);
  846. file_padding += FIRST_CONTAINER_HEADER_LENGTH;
  847. }
  848. img_sp++;
  849. } while (img_sp->option != NO_IMG);
  850. /* Add padding or skip appended container */
  851. ret = lseek(ofd, file_padding, SEEK_SET);
  852. if (ret < 0) {
  853. fprintf(stderr, "%s: lseek error %s\n",
  854. __func__, strerror(errno));
  855. exit(EXIT_FAILURE);
  856. }
  857. if (container >= 0) {
  858. /* Note: Image offset are not contained in the image */
  859. tmp = flatten_container_header(&imx_header, container + 1,
  860. &size, file_padding);
  861. /* Write image header */
  862. if (write(ofd, tmp, size) != size) {
  863. fprintf(stderr, "error writing image hdr\n");
  864. exit(EXIT_FAILURE);
  865. }
  866. /* Clean-up memory used by the headers */
  867. free(tmp);
  868. }
  869. /*
  870. * step through the image stack again this time copying
  871. * images to final bin, stop once we reach null terminator.
  872. */
  873. img_sp = image_stack;
  874. while (img_sp->option != NO_IMG) {
  875. if (img_sp->option == M40 || img_sp->option == M41 ||
  876. img_sp->option == AP || img_sp->option == DATA ||
  877. img_sp->option == SCD || img_sp->option == SCFW ||
  878. img_sp->option == SECO || img_sp->option == MSG_BLOCK ||
  879. img_sp->option == UPOWER || img_sp->option == SENTINEL) {
  880. copy_file_aligned(ofd, img_sp->filename, img_sp->src,
  881. sector_size);
  882. }
  883. img_sp++;
  884. }
  885. return 0;
  886. }
  887. int imx8image_copy_image(int outfd, struct image_tool_params *mparams)
  888. {
  889. image_t *img_sp = param_stack;
  890. /*
  891. * SECO FW is a container image, this is to calculate the
  892. * 2nd container offset.
  893. */
  894. fprintf(stdout, "parsing %s\n", mparams->imagename);
  895. parse_cfg_file(img_sp, mparams->imagename);
  896. if (sector_size == 0) {
  897. fprintf(stderr, "Wrong sector size\n");
  898. exit(EXIT_FAILURE);
  899. }
  900. fprintf(stdout, "CONTAINER Sector size:\t%08x\n", sector_size);
  901. fprintf(stdout, "CONTAINER FUSE VERSION:\t0x%02x\n", fuse_version);
  902. fprintf(stdout, "CONTAINER SW VERSION:\t0x%04x\n", sw_version);
  903. build_container(soc, sector_size, emmc_fastboot,
  904. img_sp, false, fuse_version, sw_version, outfd);
  905. return 0;
  906. }
  907. /*
  908. * imx8image parameters
  909. */
  910. U_BOOT_IMAGE_TYPE(
  911. imx8image,
  912. "NXP i.MX8 Boot Image support",
  913. 0,
  914. NULL,
  915. imx8image_check_params,
  916. NULL,
  917. imx8image_print_header,
  918. imx8image_set_header,
  919. NULL,
  920. imx8image_check_image_types,
  921. NULL,
  922. NULL
  923. );