blob: cad55fd3cf211d6ebce71c7c56ad974af52ad936 [file] [log] [blame]
Peng Fan60a56072018-10-16 04:50:30 +00001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright 2018 NXP
4 *
5 * Peng Fan <peng.fan@nxp.com>
6 */
7
8#include "imx8image.h"
Simon Glass2dc9c342020-05-10 11:40:01 -06009#include <image.h>
Alice Guocd759f32025-04-28 18:37:40 +080010#include <linux/sizes.h>
Peng Fan60a56072018-10-16 04:50:30 +000011
12static int p_idx;
13static int sector_size;
14static soc_type_t soc;
15static int container = -1;
16static int32_t core_type = CFG_CORE_INVALID;
17static bool emmc_fastboot;
Heiko Schocherfd61e712024-11-04 19:02:03 +010018static bool dcd_skip;
Peng Fan60a56072018-10-16 04:50:30 +000019static image_t param_stack[IMG_STACK_SIZE];
20static uint8_t fuse_version;
21static uint16_t sw_version;
22static uint32_t custom_partition;
23static uint32_t scfw_flags;
24
25int imx8image_check_params(struct image_tool_params *params)
26{
27 return 0;
28}
29
30static void imx8image_set_header(void *ptr, struct stat *sbuf, int ifd,
31 struct image_tool_params *params)
32{
33}
34
Pali Rohár0ed41e22023-03-29 21:25:54 +020035static void imx8image_print_header(const void *ptr, struct image_tool_params *params)
Peng Fan60a56072018-10-16 04:50:30 +000036{
37}
38
39static int imx8image_check_image_types(uint8_t type)
40{
41 return (type == IH_TYPE_IMX8IMAGE) ? EXIT_SUCCESS : EXIT_FAILURE;
42}
43
44static table_entry_t imx8image_cmds[] = {
45 {CMD_BOOT_FROM, "BOOT_FROM", "boot command", },
Heiko Schocherfd61e712024-11-04 19:02:03 +010046 {CMD_DCD_SKIP, "DCD_SKIP", "skip DCD init", },
Peng Fan60a56072018-10-16 04:50:30 +000047 {CMD_FUSE_VERSION, "FUSE_VERSION", "fuse version", },
48 {CMD_SW_VERSION, "SW_VERSION", "sw version", },
49 {CMD_MSG_BLOCK, "MSG_BLOCK", "msg block", },
50 {CMD_FILEOFF, "FILEOFF", "fileoff", },
51 {CMD_FLAG, "FLAG", "flag", },
52 {CMD_APPEND, "APPEND", "append a container", },
53 {CMD_PARTITION, "PARTITION", "new partition", },
54 {CMD_SOC_TYPE, "SOC_TYPE", "soc type", },
55 {CMD_CONTAINER, "CONTAINER", "new container", },
56 {CMD_IMAGE, "IMAGE", "new image", },
57 {CMD_DATA, "DATA", "new data", },
Alice Guocd759f32025-04-28 18:37:40 +080058 {CMD_DUMMY_V2X, "DUMMY_V2X", "v2x", },
59 {CMD_HOLD, "HOLD", "hold", },
60 {-1, "", "", }
Peng Fan60a56072018-10-16 04:50:30 +000061};
62
63static table_entry_t imx8image_core_entries[] = {
64 {CFG_SCU, "SCU", "scu core", },
Gary Bissona1e98d62024-08-05 23:25:08 +020065 {CFG_PWR, "PWR", "uPower core", },
Peng Fan60a56072018-10-16 04:50:30 +000066 {CFG_M40, "M40", "M4 core 0", },
67 {CFG_M41, "M41", "M4 core 1", },
68 {CFG_A35, "A35", "A35 core", },
Peng Faneeb23bf2022-07-26 16:41:19 +080069 {CFG_A55, "A55", "A55 core", },
Peng Fan60a56072018-10-16 04:50:30 +000070 {CFG_A53, "A53", "A53 core", },
71 {CFG_A72, "A72", "A72 core", },
Alice Guocd759f32025-04-28 18:37:40 +080072 {CFG_OEI, "OEI", "OEI", },
73 {CFG_M33, "M33", "M33 core", },
74 {-1, "", "", }
Peng Fan60a56072018-10-16 04:50:30 +000075};
76
77static table_entry_t imx8image_sector_size[] = {
78 {0x400, "sd", "sd/emmc",},
79 {0x400, "emmc_fastboot", "emmc fastboot",},
80 {0x400, "fspi", "flexspi", },
81 {0x1000, "nand_4k", "nand 4K", },
82 {0x2000, "nand_8k", "nand 8K", },
83 {0x4000, "nand_16k", "nand 16K", },
84 {-1, "", "Invalid", },
85};
86
87static void parse_cfg_cmd(image_t *param_stack, int32_t cmd, char *token,
88 char *name, int lineno)
89{
90 switch (cmd) {
91 case CMD_BOOT_FROM:
92 sector_size = get_table_entry_id(imx8image_sector_size,
93 "imximage boot option",
94 token);
95 if (!strncmp("emmc_fastboot", token, 13))
96 emmc_fastboot = true;
97 break;
Heiko Schocherfd61e712024-11-04 19:02:03 +010098 case CMD_DCD_SKIP:
99 if (!strncmp("true", token, 4))
100 dcd_skip = true;
Fabio Estevama95e8322024-11-11 23:38:54 -0300101 break;
Peng Fan60a56072018-10-16 04:50:30 +0000102 case CMD_FUSE_VERSION:
103 fuse_version = (uint8_t)(strtoll(token, NULL, 0) & 0xFF);
104 break;
105 case CMD_SW_VERSION:
106 sw_version = (uint8_t)(strtoll(token, NULL, 0) & 0xFFFF);
107 break;
108 case CMD_FILEOFF:
109 param_stack[p_idx].option = FILEOFF;
110 param_stack[p_idx++].dst = (uint32_t)strtoll(token, NULL, 0);
111 break;
112 case CMD_MSG_BLOCK:
113 param_stack[p_idx].option = MSG_BLOCK;
114 param_stack[p_idx].filename = token;
115 break;
116 case CMD_FLAG:
117 param_stack[p_idx].option = FLAG;
118 param_stack[p_idx++].entry = (uint32_t)strtoll(token, NULL, 0);
119 break;
120 case CMD_APPEND:
121 param_stack[p_idx].option = APPEND;
122 param_stack[p_idx++].filename = token;
123 break;
124 case CMD_PARTITION:
125 param_stack[p_idx].option = PARTITION;
126 param_stack[p_idx++].entry = (uint32_t)strtoll(token, NULL, 0);
127 break;
128 case CMD_SOC_TYPE:
129 if (!strncmp(token, "IMX8QX", 6)) {
130 soc = QX;
131 } else if (!strncmp(token, "IMX8QM", 6)) {
132 soc = QM;
Peng Faneeb23bf2022-07-26 16:41:19 +0800133 } else if (!strncmp(token, "ULP", 3)) {
Gary Bisson70365802024-08-05 23:25:07 +0200134 soc = ULP;
Peng Faneeb23bf2022-07-26 16:41:19 +0800135 } else if (!strncmp(token, "IMX9", 4)) {
136 soc = IMX9;
Peng Fan60a56072018-10-16 04:50:30 +0000137 } else {
138 fprintf(stderr, "Unknown CMD_SOC_TYPE");
139 exit(EXIT_FAILURE);
140 }
141 break;
142 case CMD_IMAGE:
143 case CMD_DATA:
144 core_type = get_table_entry_id(imx8image_core_entries,
145 "imx8image core entries",
146 token);
147 if (core_type < 0) {
148 fprintf(stderr, "Wrong IMAGE core_type %s\n", token);
149 exit(EXIT_FAILURE);
150 }
151 break;
Alice Guocd759f32025-04-28 18:37:40 +0800152 case CMD_DUMMY_V2X:
153 param_stack[p_idx].option = DUMMY_V2X;
154 param_stack[p_idx++].entry = (uint32_t)strtoll(token, NULL, 0);
155 break;
156 case CMD_HOLD:
157 param_stack[p_idx].option = HOLD;
158 param_stack[p_idx].entry = (uint32_t)strtoll(token, NULL, 0);
159 param_stack[p_idx++].filename = NULL;
Peng Fan60a56072018-10-16 04:50:30 +0000160 default:
161 break;
162 }
163}
164
165static void parse_cfg_fld(image_t *param_stack, int32_t *cmd, char *token,
166 char *name, int lineno, int fld)
167{
168 switch (fld) {
169 case CFG_COMMAND:
170 *cmd = get_table_entry_id(imx8image_cmds, "imx8image cmds",
171 token);
172 if (*cmd < 0) {
173 fprintf(stderr, "Error: %s[%d] - Invalid command (%s)\n", name, lineno, token);
174 exit(EXIT_FAILURE);
175 }
176
177 if (*cmd == CMD_CONTAINER) {
178 fprintf(stdout, "New Container: \t%d\n", ++container);
179 param_stack[p_idx++].option = NEW_CONTAINER;
180 }
181 break;
182 case CFG_CORE_TYPE:
183 parse_cfg_cmd(param_stack, *cmd, token, name, lineno);
184 break;
185 case CFG_IMAGE_NAME:
186 if (*cmd == CMD_MSG_BLOCK) {
187 if (!strncmp(token, "fuse", 4)) {
188 param_stack[p_idx].ext = SC_R_OTP;
189 } else if (!strncmp(token, "debug", 5)) {
190 param_stack[p_idx].ext = SC_R_DEBUG;
191 } else if (!strncmp(token, "field", 5)) {
192 param_stack[p_idx].ext = SC_R_ROM_0;
193 } else {
194 fprintf(stderr, "MSG type not found %s\n", token);
195 exit(EXIT_FAILURE);
196 }
197 break;
198 }
199 switch (core_type) {
200 case CFG_SCU:
201 param_stack[p_idx].option = SCFW;
202 param_stack[p_idx++].filename = token;
203 break;
Gary Bissona1e98d62024-08-05 23:25:08 +0200204 case CFG_PWR:
205 param_stack[p_idx].option = UPOWER;
206 param_stack[p_idx++].filename = token;
207 break;
Peng Fan60a56072018-10-16 04:50:30 +0000208 case CFG_M40:
209 param_stack[p_idx].option = M40;
210 param_stack[p_idx].ext = 0;
211 param_stack[p_idx].filename = token;
212 break;
213 case CFG_M41:
214 param_stack[p_idx].option = M41;
215 param_stack[p_idx].ext = 1;
216 param_stack[p_idx].filename = token;
217 break;
218 case CFG_A35:
Peng Faneeb23bf2022-07-26 16:41:19 +0800219 case CFG_A55:
Peng Fan60a56072018-10-16 04:50:30 +0000220 param_stack[p_idx].ext = CORE_CA35;
221 param_stack[p_idx].option =
222 (*cmd == CMD_DATA) ? DATA : AP;
223 param_stack[p_idx].filename = token;
224 break;
225 case CFG_A53:
226 param_stack[p_idx].ext = CORE_CA53;
227 param_stack[p_idx].option =
228 (*cmd == CMD_DATA) ? DATA : AP;
229 param_stack[p_idx].filename = token;
230 break;
231 case CFG_A72:
232 param_stack[p_idx].ext = CORE_CA72;
233 param_stack[p_idx].option =
234 (*cmd == CMD_DATA) ? DATA : AP;
235 param_stack[p_idx].filename = token;
Alice Guocd759f32025-04-28 18:37:40 +0800236 break;
237 case CFG_OEI:
238 param_stack[p_idx].option = OEI;
239 param_stack[p_idx].filename = token;
240 param_stack[p_idx].ext = CORE_CM4_0;
241 break;
242 case CFG_M33:
243 param_stack[p_idx].option = M40;
244 param_stack[p_idx].ext = 0;
245 param_stack[p_idx].filename = token;
Peng Fan60a56072018-10-16 04:50:30 +0000246 break;
247 }
248 break;
249 case CFG_LOAD_ADDR:
250 if (*cmd == CMD_MSG_BLOCK) {
251 param_stack[p_idx++].entry =
252 (uint32_t)strtoll(token, NULL, 0);
253 break;
254 }
255 switch (core_type) {
256 case CFG_SCU:
257 break;
258 case CFG_M40:
259 case CFG_M41:
260 case CFG_A35:
261 case CFG_A53:
Peng Faneeb23bf2022-07-26 16:41:19 +0800262 case CFG_A55:
Peng Fan60a56072018-10-16 04:50:30 +0000263 case CFG_A72:
Alice Guocd759f32025-04-28 18:37:40 +0800264 case CFG_M33:
Peng Fan60a56072018-10-16 04:50:30 +0000265 param_stack[p_idx++].entry =
266 (uint32_t)strtoll(token, NULL, 0);
267 break;
Alice Guocd759f32025-04-28 18:37:40 +0800268 case CFG_OEI:
269 param_stack[p_idx].dst = (uint32_t)strtoll(token, NULL, 0);
270 param_stack[p_idx].entry = param_stack[p_idx].dst + 1;
271 p_idx++;
272 break;
Peng Fan60a56072018-10-16 04:50:30 +0000273 }
274 default:
275 break;
276 }
277}
278
279static uint32_t parse_cfg_file(image_t *param_stack, char *name)
280{
281 FILE *fd = NULL;
282 char *line = NULL;
283 char *token, *saveptr1, *saveptr2;
284 int lineno = 0;
285 int fld;
286 size_t len;
287 int32_t cmd;
288
289 fd = fopen(name, "r");
290 if (fd == 0) {
291 fprintf(stderr, "Error: %s - Can't open cfg file\n", name);
292 exit(EXIT_FAILURE);
293 }
294
295 /*
296 * Very simple parsing, line starting with # are comments
297 * and are dropped
298 */
299 while ((getline(&line, &len, fd)) > 0) {
300 lineno++;
301
302 token = strtok_r(line, "\r\n", &saveptr1);
303 if (!token)
304 continue;
305
306 /* Check inside the single line */
307 for (fld = CFG_COMMAND, cmd = CFG_INVALID,
308 line = token; ; line = NULL, fld++) {
309 token = strtok_r(line, " \t", &saveptr2);
310 if (!token)
311 break;
312
313 /* Drop all text starting with '#' as comments */
314 if (token[0] == '#')
315 break;
316
317 parse_cfg_fld(param_stack, &cmd, token, name, lineno,
318 fld);
319 }
320 }
321
Maks Mishin2b3d0b72025-02-02 20:05:17 +0300322 free(line);
Mikhail Ilin7ed5b722022-11-23 13:59:49 +0300323 fclose(fd);
Peng Fan60a56072018-10-16 04:50:30 +0000324 return 0;
325}
326
327static void check_file(struct stat *sbuf, char *filename)
328{
329 int tmp_fd = open(filename, O_RDONLY | O_BINARY);
330
331 if (tmp_fd < 0) {
332 fprintf(stderr, "%s: Can't open: %s\n",
333 filename, strerror(errno));
334 exit(EXIT_FAILURE);
335 }
336
337 if (fstat(tmp_fd, sbuf) < 0) {
338 fprintf(stderr, "%s: Can't stat: %s\n",
339 filename, strerror(errno));
340 exit(EXIT_FAILURE);
341 }
342
343 close(tmp_fd);
344}
345
346static void copy_file_aligned(int ifd, const char *datafile, int offset,
347 int align)
348{
349 int dfd;
350 struct stat sbuf;
351 unsigned char *ptr;
352 uint8_t zeros[0x4000];
353 int size;
Peng Fan00c2dd52018-11-05 09:53:22 +0000354 int ret;
Peng Fan60a56072018-10-16 04:50:30 +0000355
356 if (align > 0x4000) {
357 fprintf(stderr, "Wrong alignment requested %d\n", align);
358 exit(EXIT_FAILURE);
359 }
360
361 memset(zeros, 0, sizeof(zeros));
362
363 dfd = open(datafile, O_RDONLY | O_BINARY);
364 if (dfd < 0) {
365 fprintf(stderr, "Can't open %s: %s\n",
366 datafile, strerror(errno));
367 exit(EXIT_FAILURE);
368 }
369
370 if (fstat(dfd, &sbuf) < 0) {
371 fprintf(stderr, "Can't stat %s: %s\n",
372 datafile, strerror(errno));
373 exit(EXIT_FAILURE);
374 }
375
376 if (sbuf.st_size == 0)
377 goto close;
378
379 ptr = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, dfd, 0);
380 if (ptr == MAP_FAILED) {
381 fprintf(stderr, "Can't read %s: %s\n",
382 datafile, strerror(errno));
383 exit(EXIT_FAILURE);
384 }
385
386 size = sbuf.st_size;
Peng Fan00c2dd52018-11-05 09:53:22 +0000387 ret = lseek(ifd, offset, SEEK_SET);
388 if (ret < 0) {
389 fprintf(stderr, "%s: lseek error %s\n",
390 __func__, strerror(errno));
391 exit(EXIT_FAILURE);
392 }
393
Peng Fan60a56072018-10-16 04:50:30 +0000394 if (write(ifd, ptr, size) != size) {
395 fprintf(stderr, "Write error %s\n", strerror(errno));
396 exit(EXIT_FAILURE);
397 }
398
399 align = ALIGN(size, align) - size;
400
401 if (write(ifd, (char *)&zeros, align) != align) {
402 fprintf(stderr, "Write error: %s\n", strerror(errno));
403 exit(EXIT_FAILURE);
404 }
405
406 munmap((void *)ptr, sbuf.st_size);
407close:
408 close(dfd);
409}
410
411static void copy_file (int ifd, const char *datafile, int pad, int offset)
412{
413 int dfd;
414 struct stat sbuf;
415 unsigned char *ptr;
416 int tail;
Peng Fane3ed0cc2021-03-19 15:56:53 +0800417 uint64_t zero = 0;
Peng Fan60a56072018-10-16 04:50:30 +0000418 uint8_t zeros[4096];
Peng Fan00c2dd52018-11-05 09:53:22 +0000419 int size, ret;
Peng Fan60a56072018-10-16 04:50:30 +0000420
421 memset(zeros, 0, sizeof(zeros));
422
423 dfd = open(datafile, O_RDONLY | O_BINARY);
424 if (dfd < 0) {
425 fprintf(stderr, "Can't open %s: %s\n",
426 datafile, strerror(errno));
427 exit(EXIT_FAILURE);
428 }
429
430 if (fstat(dfd, &sbuf) < 0) {
431 fprintf(stderr, "Can't stat %s: %s\n",
432 datafile, strerror(errno));
433 exit(EXIT_FAILURE);
434 }
435
436 if (sbuf.st_size == 0)
437 goto close;
438
439 ptr = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, dfd, 0);
440 if (ptr == MAP_FAILED) {
441 fprintf(stderr, "Can't read %s: %s\n",
442 datafile, strerror(errno));
443 exit(EXIT_FAILURE);
444 }
445
446 size = sbuf.st_size;
Peng Fan00c2dd52018-11-05 09:53:22 +0000447 ret = lseek(ifd, offset, SEEK_SET);
448 if (ret < 0) {
449 fprintf(stderr, "%s: lseek error %s\n",
450 __func__, strerror(errno));
451 exit(EXIT_FAILURE);
452 }
453
Peng Fan60a56072018-10-16 04:50:30 +0000454 if (write(ifd, ptr, size) != size) {
455 fprintf(stderr, "Write error %s\n",
456 strerror(errno));
457 exit(EXIT_FAILURE);
458 }
459
460 tail = size % 4;
461 pad = pad - size;
462 if (pad == 1 && tail != 0) {
463 if (write(ifd, (char *)&zero, 4 - tail) != 4 - tail) {
464 fprintf(stderr, "Write error on %s\n",
465 strerror(errno));
466 exit(EXIT_FAILURE);
467 }
468 } else if (pad > 1) {
469 while (pad > 0) {
470 int todo = sizeof(zeros);
471
472 if (todo > pad)
473 todo = pad;
474 if (write(ifd, (char *)&zeros, todo) != todo) {
475 fprintf(stderr, "Write error: %s\n",
476 strerror(errno));
477 exit(EXIT_FAILURE);
478 }
479 pad -= todo;
480 }
481 }
482
483 munmap((void *)ptr, sbuf.st_size);
484close:
485 close(dfd);
486}
487
488uint64_t read_dcd_offset(char *filename)
489{
490 int dfd;
491 struct stat sbuf;
492 uint8_t *ptr;
493 uint64_t offset = 0;
494
495 dfd = open(filename, O_RDONLY | O_BINARY);
496 if (dfd < 0) {
497 fprintf(stderr, "Can't open %s: %s\n", filename, strerror(errno));
498 exit(EXIT_FAILURE);
499 }
500
501 if (fstat(dfd, &sbuf) < 0) {
502 fprintf(stderr, "Can't stat %s: %s\n", filename, strerror(errno));
503 exit(EXIT_FAILURE);
504 }
505
506 ptr = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, dfd, 0);
507 if (ptr == MAP_FAILED) {
508 fprintf(stderr, "Can't read %s: %s\n", filename, strerror(errno));
509 exit(EXIT_FAILURE);
510 }
511
512 offset = *(uint32_t *)(ptr + DCD_ENTRY_ADDR_IN_SCFW);
513
514 munmap((void *)ptr, sbuf.st_size);
515 close(dfd);
516
517 return offset;
518}
519
520static void set_image_hash(boot_img_t *img, char *filename, uint32_t hash_type)
521{
522 FILE *fp = NULL;
523 char sha_command[512];
524 char hash[2 * HASH_MAX_LEN + 1];
525 int i, ret;
526
527 if (img->size == 0)
528 sprintf(sha_command, "sha%dsum /dev/null", hash_type);
529 else
530 sprintf(sha_command, "dd if=/dev/zero of=tmp_pad bs=%d count=1;\
531 dd if=\'%s\' of=tmp_pad conv=notrunc;\
532 sha%dsum tmp_pad; rm -f tmp_pad",
533 img->size, filename, hash_type);
534
535 switch (hash_type) {
536 case HASH_TYPE_SHA_256:
537 img->hab_flags |= IMG_FLAG_HASH_SHA256;
538 break;
539 case HASH_TYPE_SHA_384:
540 img->hab_flags |= IMG_FLAG_HASH_SHA384;
541 break;
542 case HASH_TYPE_SHA_512:
543 img->hab_flags |= IMG_FLAG_HASH_SHA512;
544 break;
545 default:
546 fprintf(stderr, "Wrong hash type selected (%d) !!!\n\n",
547 hash_type);
548 exit(EXIT_FAILURE);
549 break;
550 }
551 memset(img->hash, 0, HASH_MAX_LEN);
552
553 fp = popen(sha_command, "r");
554 if (!fp) {
555 fprintf(stderr, "Failed to run command hash\n");
556 exit(EXIT_FAILURE);
557 }
558
559 if (!fgets(hash, hash_type / 4 + 1, fp)) {
560 fprintf(stderr, "Failed to hash file: %s\n", filename);
561 exit(EXIT_FAILURE);
562 }
563
564 for (i = 0; i < strlen(hash) / 2; i++) {
565 ret = sscanf(hash + 2 * i, "%02hhx", &img->hash[i]);
566 if (ret < 0) {
567 fprintf(stderr, "Failed sscanf hash: %d\n", ret);
568 exit(EXIT_FAILURE);
569 }
570 }
571
572 pclose(fp);
573}
574
575static void set_image_array_entry(flash_header_v3_t *container,
576 soc_type_t soc, const image_t *image_stack,
577 uint32_t offset, uint32_t size,
578 char *tmp_filename, bool dcd_skip)
579{
580 uint64_t entry = image_stack->entry;
Alice Guocd759f32025-04-28 18:37:40 +0800581 uint64_t dst = image_stack->dst;
Peng Fan60a56072018-10-16 04:50:30 +0000582 uint64_t core = image_stack->ext;
583 uint32_t meta;
584 char *tmp_name = "";
585 option_type_t type = image_stack->option;
586 boot_img_t *img = &container->img[container->num_images];
587
588 img->offset = offset; /* Is re-adjusted later */
589 img->size = size;
590
Alice Guocd759f32025-04-28 18:37:40 +0800591 if (type != DUMMY_V2X) {
592 set_image_hash(img, tmp_filename, IMAGE_HASH_ALGO_DEFAULT);
593 }
Peng Fan60a56072018-10-16 04:50:30 +0000594
595 switch (type) {
596 case SECO:
597 img->hab_flags |= IMG_TYPE_SECO;
598 img->hab_flags |= CORE_SECO << BOOT_IMG_FLAGS_CORE_SHIFT;
599 tmp_name = "SECO";
600 img->dst = 0x20C00000;
601 img->entry = 0x20000000;
602 break;
Peng Faneeb23bf2022-07-26 16:41:19 +0800603 case SENTINEL:
604 if (container->num_images > 0) {
605 fprintf(stderr, "Error: SENTINEL container only allows 1 image\n");
606 return;
607 }
608
609 img->hab_flags |= IMG_TYPE_SENTINEL;
610 img->hab_flags |= CORE_ULP_SENTINEL << BOOT_IMG_FLAGS_CORE_SHIFT;
611 tmp_name = "SENTINEL";
612 img->dst = 0xe4000000; /* S400 IRAM base */
613 img->entry = 0xe4000000;
614 break;
Alice Guocd759f32025-04-28 18:37:40 +0800615 case OEI:
616 if (soc != IMX9) {
617 fprintf(stderr, "Error: invalid core id: %" PRIi64 "\n", core);
618 exit(EXIT_FAILURE);
619 }
620
621 img->hab_flags |= IMG_TYPE_OEI;
622 if (core == CORE_CM4_0) {
623 img->hab_flags |= CORE_ULP_CM33 << BOOT_IMG_FLAGS_CORE_SHIFT;
624 meta = CORE_IMX95_M33P;
625
626 } else {
627 img->hab_flags |= CORE_ULP_CA35 << BOOT_IMG_FLAGS_CORE_SHIFT;
628 meta = CORE_IMX95_A55C0;
629 }
630 tmp_name = "OEI";
631 img->dst = (dst ? dst : entry);
632 img->entry = entry;
633 img->meta = meta;
634 custom_partition = 0;
635 break;
Peng Fan60a56072018-10-16 04:50:30 +0000636 case AP:
637 if (soc == QX && core == CORE_CA35) {
638 meta = IMAGE_A35_DEFAULT_META(custom_partition);
639 } else if (soc == QM && core == CORE_CA53) {
640 meta = IMAGE_A53_DEFAULT_META(custom_partition);
641 } else if (soc == QM && core == CORE_CA72) {
642 meta = IMAGE_A72_DEFAULT_META(custom_partition);
Alice Guocd759f32025-04-28 18:37:40 +0800643 } else if ((soc == ULP) && core == CORE_CA35) {
Peng Faneeb23bf2022-07-26 16:41:19 +0800644 meta = 0;
Alice Guocd759f32025-04-28 18:37:40 +0800645 } else if ((soc == IMX9) && core == CORE_CA35) {
646 meta = CORE_IMX95_A55C0;
Peng Fan60a56072018-10-16 04:50:30 +0000647 } else {
Heinrich Schuchardt819abf82018-12-17 10:22:21 +0100648 fprintf(stderr,
649 "Error: invalid AP core id: %" PRIu64 "\n",
Peng Fan60a56072018-10-16 04:50:30 +0000650 core);
651 exit(EXIT_FAILURE);
652 }
653 img->hab_flags |= IMG_TYPE_EXEC;
Peng Faneeb23bf2022-07-26 16:41:19 +0800654 if ((soc == ULP) || (soc == IMX9))
655 img->hab_flags |= CORE_ULP_CA35 << BOOT_IMG_FLAGS_CORE_SHIFT;
656 else
657 img->hab_flags |= CORE_CA53 << BOOT_IMG_FLAGS_CORE_SHIFT; /* On B0, only core id = 4 is valid */
Peng Fan60a56072018-10-16 04:50:30 +0000658 tmp_name = "AP";
659 img->dst = entry;
660 img->entry = entry;
661 img->meta = meta;
662 custom_partition = 0;
663 break;
664 case M40:
665 case M41:
Peng Faneeb23bf2022-07-26 16:41:19 +0800666 if ((soc == ULP) || (soc == IMX9)) {
667 core = CORE_ULP_CM33;
668 meta = 0;
Peng Fan60a56072018-10-16 04:50:30 +0000669 } else {
Peng Faneeb23bf2022-07-26 16:41:19 +0800670 if (core == 0) {
671 core = CORE_CM4_0;
672 meta = IMAGE_M4_0_DEFAULT_META(custom_partition);
673 } else if (core == 1) {
674 core = CORE_CM4_1;
675 meta = IMAGE_M4_1_DEFAULT_META(custom_partition);
676 } else {
677 fprintf(stderr,
678 "Error: invalid m4 core id: %" PRIu64 "\n",
679 core);
680 exit(EXIT_FAILURE);
681 }
Peng Fan60a56072018-10-16 04:50:30 +0000682 }
683 img->hab_flags |= IMG_TYPE_EXEC;
684 img->hab_flags |= core << BOOT_IMG_FLAGS_CORE_SHIFT;
685 tmp_name = "M4";
686 if ((entry & 0x7) != 0) {
687 fprintf(stderr, "\n\nWarning: M4 Destination address is not 8 byte aligned\n\n");
688 exit(EXIT_FAILURE);
689 }
690 img->dst = entry;
691 img->entry = entry;
692 img->meta = meta;
693 custom_partition = 0;
694 break;
695 case DATA:
696 img->hab_flags |= IMG_TYPE_DATA;
Peng Faneeb23bf2022-07-26 16:41:19 +0800697 if ((soc == ULP) || (soc == IMX9)) {
698 if (core == CORE_CM4_0)
699 img->hab_flags |= CORE_ULP_CM33 << BOOT_IMG_FLAGS_CORE_SHIFT;
700 else
701 img->hab_flags |= CORE_ULP_CA35 << BOOT_IMG_FLAGS_CORE_SHIFT;
702 } else {
703 img->hab_flags |= CORE_CA35 << BOOT_IMG_FLAGS_CORE_SHIFT;
704 }
Peng Fan60a56072018-10-16 04:50:30 +0000705 tmp_name = "DATA";
706 img->dst = entry;
707 break;
708 case MSG_BLOCK:
709 img->hab_flags |= IMG_TYPE_DATA;
710 img->hab_flags |= CORE_CA35 << BOOT_IMG_FLAGS_CORE_SHIFT;
711 img->meta = core << BOOT_IMG_META_MU_RID_SHIFT;
712 tmp_name = "MSG_BLOCK";
713 img->dst = entry;
714 break;
715 case SCFW:
716 img->hab_flags |= scfw_flags & 0xFFFF0000;
717 img->hab_flags |= IMG_TYPE_EXEC;
718 img->hab_flags |= CORE_SC << BOOT_IMG_FLAGS_CORE_SHIFT;
719 tmp_name = "SCFW";
720 img->dst = 0x1FFE0000;
721 img->entry = 0x1FFE0000;
722
723 /* Lets add the DCD now */
724 if (!dcd_skip) {
725 container->num_images++;
726 img = &container->img[container->num_images];
727 img->hab_flags |= IMG_TYPE_DCD_DDR;
728 img->hab_flags |= CORE_SC << BOOT_IMG_FLAGS_CORE_SHIFT;
729 set_image_hash(img, "/dev/null",
730 IMAGE_HASH_ALGO_DEFAULT);
731 img->offset = offset + img->size;
732 img->entry = read_dcd_offset(tmp_filename);
733 img->dst = img->entry - 1;
734 }
735 break;
Peng Faneeb23bf2022-07-26 16:41:19 +0800736 case UPOWER:
737 if (soc == ULP) {
738 img->hab_flags |= IMG_TYPE_EXEC;
739 img->hab_flags |= CORE_ULP_UPOWER << BOOT_IMG_FLAGS_CORE_SHIFT;
740 tmp_name = "UPOWER";
741 img->dst = 0x28300200; /* UPOWER code RAM */
742 img->entry = 0x28300200;
743 }
744 break;
Alice Guocd759f32025-04-28 18:37:40 +0800745 case DUMMY_V2X:
746 img->hab_flags |= IMG_TYPE_V2X_DUMMY;
747 img->hab_flags |= CORE_SC << BOOT_IMG_FLAGS_CORE_SHIFT;
748 tmp_name = "V2X Dummy";
749 set_image_hash(img, "/dev/null", IMAGE_HASH_ALGO_DEFAULT);
750 img->dst = entry;
751 img->entry = entry;
752 img->size = 0; /* dummy image has no size */
753 break;
Peng Fan60a56072018-10-16 04:50:30 +0000754 default:
755 fprintf(stderr, "unrecognized image type (%d)\n", type);
756 exit(EXIT_FAILURE);
757 }
758
759 fprintf(stdout, "%s file_offset = 0x%x size = 0x%x\n", tmp_name, offset, size);
760
761 container->num_images++;
762}
763
764void set_container(flash_header_v3_t *container, uint16_t sw_version,
765 uint32_t alignment, uint32_t flags, uint16_t fuse_version)
766{
767 container->sig_blk_hdr.tag = 0x90;
768 container->sig_blk_hdr.length = sizeof(sig_blk_hdr_t);
769 container->sw_version = sw_version;
770 container->padding = alignment;
771 container->fuse_version = fuse_version;
772 container->flags = flags;
773 fprintf(stdout, "container flags: 0x%x\n", container->flags);
774}
775
Alice Guocd759f32025-04-28 18:37:40 +0800776static int get_container_image_start_pos(image_t *image_stack, uint32_t align, uint32_t *v2x)
Peng Fan60a56072018-10-16 04:50:30 +0000777{
778 image_t *img_sp = image_stack;
779 /*8K total container header*/
780 int file_off = CONTAINER_IMAGE_ARRAY_START_OFFSET;
781 FILE *fd = NULL;
Alice Guocd759f32025-04-28 18:37:40 +0800782 flash_header_v3_t *header;
783 flash_header_v3_t *header2;
784 void *p;
Peng Fan60a56072018-10-16 04:50:30 +0000785 int ret;
786
Alice Guocd759f32025-04-28 18:37:40 +0800787 p = calloc(1, SZ_4K);
788 if (!p) {
789 fprintf(stderr, "Fail to alloc 4K memory\n");
790 exit(EXIT_FAILURE);
791 }
792
793 header = p;
794 header2 = p + FIRST_CONTAINER_HEADER_LENGTH;
795
Peng Fan60a56072018-10-16 04:50:30 +0000796 while (img_sp->option != NO_IMG) {
797 if (img_sp->option == APPEND) {
798 fd = fopen(img_sp->filename, "r");
799 if (!fd) {
800 fprintf(stderr, "Fail open first container file %s\n", img_sp->filename);
801 exit(EXIT_FAILURE);
802 }
803
Alice Guocd759f32025-04-28 18:37:40 +0800804 ret = fread(header, SZ_4K, 1, fd);
Peng Fand65dcfd2018-11-05 09:53:25 +0000805 if (ret != 1) {
Peng Fan60a56072018-10-16 04:50:30 +0000806 printf("Failure Read header %d\n", ret);
Peng Fand65dcfd2018-11-05 09:53:25 +0000807 exit(EXIT_FAILURE);
808 }
Peng Fan60a56072018-10-16 04:50:30 +0000809
810 fclose(fd);
811
Alice Guocd759f32025-04-28 18:37:40 +0800812 if (header->tag != IVT_HEADER_TAG_B0) {
813 fprintf(stderr, "header tag mismatched \n");
Peng Fan60a56072018-10-16 04:50:30 +0000814 exit(EXIT_FAILURE);
815 } else {
Alice Guocd759f32025-04-28 18:37:40 +0800816 if (header2->tag != IVT_HEADER_TAG_B0) {
817 file_off += header->img[header->num_images - 1].size;
818 file_off = ALIGN(file_off, align);
819 } else {
820 file_off = header2->img[header2->num_images - 1].offset + FIRST_CONTAINER_HEADER_LENGTH;
821 file_off += header2->img[header2->num_images - 1].size;
822 file_off = ALIGN(file_off, align);
823 fprintf(stderr, "Has 2nd container %x\n", file_off);
824 *v2x = true;
825 }
Peng Fan60a56072018-10-16 04:50:30 +0000826 }
827 }
828
829 img_sp++;
830 }
831
Alice Guocd759f32025-04-28 18:37:40 +0800832 free(p);
Peng Fan60a56072018-10-16 04:50:30 +0000833 return file_off;
834}
835
836static void set_imx_hdr_v3(imx_header_v3_t *imxhdr, uint32_t cont_id)
837{
838 flash_header_v3_t *fhdr_v3 = &imxhdr->fhdr[cont_id];
839
840 /* Set magic number, Only >= B0 supported */
841 fhdr_v3->tag = IVT_HEADER_TAG_B0;
842 fhdr_v3->version = IVT_VERSION_B0;
843}
844
845static uint8_t *flatten_container_header(imx_header_v3_t *imx_header,
846 uint8_t containers_count,
847 uint32_t *size_out,
848 uint32_t file_offset)
849{
850 uint8_t *flat = NULL;
851 uint8_t *ptr = NULL;
852 uint16_t size = 0;
853 int i, j;
854
855 /* Compute size of all container headers */
856 for (i = 0; i < containers_count; i++) {
857 flash_header_v3_t *container = &imx_header->fhdr[i];
858
859 container->sig_blk_offset = HEADER_IMG_ARRAY_OFFSET +
860 container->num_images * IMG_ARRAY_ENTRY_SIZE;
861
862 container->length = HEADER_IMG_ARRAY_OFFSET +
863 (IMG_ARRAY_ENTRY_SIZE * container->num_images) +
864 sizeof(sig_blk_hdr_t);
865
866 /* Print info needed by CST to sign the container header */
867 fprintf(stdout, "CST: CONTAINER %d offset: 0x%x\n",
868 i, file_offset + size);
869 fprintf(stdout, "CST: CONTAINER %d: Signature Block: offset is at 0x%x\n", i,
870 file_offset + size + container->length -
871 SIGNATURE_BLOCK_HEADER_LENGTH);
872
873 size += ALIGN(container->length, container->padding);
874 }
875
876 flat = calloc(size, sizeof(uint8_t));
877 if (!flat) {
878 fprintf(stderr, "Failed to allocate memory (%d)\n", size);
879 exit(EXIT_FAILURE);
880 }
881
882 ptr = flat;
883 *size_out = size;
884
885 for (i = 0; i < containers_count; i++) {
886 flash_header_v3_t *container = &imx_header->fhdr[i];
887 uint32_t container_start_offset = ptr - flat;
888
889 /* Append container header */
890 append(ptr, container, HEADER_IMG_ARRAY_OFFSET);
891
892 /* Adjust images offset to start from container headers start */
893 for (j = 0; j < container->num_images; j++) {
894 container->img[j].offset -=
895 container_start_offset + file_offset;
896 }
897 /* Append each image array entry */
898 for (j = 0; j < container->num_images; j++)
899 append(ptr, &container->img[j], sizeof(boot_img_t));
900
901 append(ptr, &container->sig_blk_hdr, sizeof(sig_blk_hdr_t));
902
903 /* Padding for container (if necessary) */
904 ptr += ALIGN(container->length, container->padding) -
905 container->length;
906 }
907
908 return flat;
909}
910
911static int build_container(soc_type_t soc, uint32_t sector_size,
912 bool emmc_fastboot, image_t *image_stack,
913 bool dcd_skip, uint8_t fuse_version,
914 uint16_t sw_version, int ofd)
915{
916 static imx_header_v3_t imx_header;
917 image_t *img_sp = image_stack;
918 int file_off;
919 uint8_t *tmp;
920 struct stat sbuf;
921 char *tmp_filename = NULL;
922 uint32_t size = 0;
923 uint32_t file_padding = 0;
Alice Guocd759f32025-04-28 18:37:40 +0800924 uint32_t v2x = false;
Peng Fan00c2dd52018-11-05 09:53:22 +0000925 int ret;
Peng Fan60a56072018-10-16 04:50:30 +0000926
927 int container = -1;
Peng Fan60a56072018-10-16 04:50:30 +0000928
929 memset((char *)&imx_header, 0, sizeof(imx_header_v3_t));
930
931 if (!image_stack) {
932 fprintf(stderr, "Empty image stack ");
933 exit(EXIT_FAILURE);
934 }
935
936 if (soc == QX)
937 fprintf(stdout, "Platform:\ti.MX8QXP B0\n");
938 else if (soc == QM)
939 fprintf(stdout, "Platform:\ti.MX8QM B0\n");
Peng Faneeb23bf2022-07-26 16:41:19 +0800940 else if (soc == ULP)
941 fprintf(stdout, "Platform:\ti.MX8ULP A0\n");
942 else if (soc == IMX9)
943 fprintf(stdout, "Platform:\ti.MX9\n");
Peng Fan60a56072018-10-16 04:50:30 +0000944
945 set_imx_hdr_v3(&imx_header, 0);
946 set_imx_hdr_v3(&imx_header, 1);
947
Alice Guocd759f32025-04-28 18:37:40 +0800948 file_off = get_container_image_start_pos(image_stack, sector_size, &v2x);
Peng Fan60a56072018-10-16 04:50:30 +0000949 fprintf(stdout, "container image offset (aligned):%x\n", file_off);
950
951 /* step through image stack and generate the header */
952 img_sp = image_stack;
953
954 /* stop once we reach null terminator */
955 while (img_sp->option != NO_IMG) {
956 switch (img_sp->option) {
Alice Guocd759f32025-04-28 18:37:40 +0800957 case OEI:
Peng Fan60a56072018-10-16 04:50:30 +0000958 case AP:
959 case M40:
960 case M41:
961 case SCFW:
962 case DATA:
Peng Faneeb23bf2022-07-26 16:41:19 +0800963 case UPOWER:
Peng Fan60a56072018-10-16 04:50:30 +0000964 case MSG_BLOCK:
Peng Fanf107b0f2018-11-05 09:53:28 +0000965 if (container < 0) {
966 fprintf(stderr, "No container found\n");
967 exit(EXIT_FAILURE);
968 }
Peng Fan60a56072018-10-16 04:50:30 +0000969 check_file(&sbuf, img_sp->filename);
970 tmp_filename = img_sp->filename;
971 set_image_array_entry(&imx_header.fhdr[container],
972 soc, img_sp, file_off,
973 ALIGN(sbuf.st_size, sector_size),
974 tmp_filename, dcd_skip);
975 img_sp->src = file_off;
976
977 file_off += ALIGN(sbuf.st_size, sector_size);
Peng Fan60a56072018-10-16 04:50:30 +0000978 break;
979
Alice Guocd759f32025-04-28 18:37:40 +0800980 case DUMMY_V2X:
981 if (container < 0) {
982 fprintf(stderr, "No container found\n");
983 exit(EXIT_FAILURE);
984 }
985 tmp_filename = "dummy";
986 set_image_array_entry(&imx_header.fhdr[container],
987 soc,
988 img_sp,
989 file_off,
990 0,
991 tmp_filename,
992 dcd_skip);
993 img_sp->src = file_off;
994 break;
995
996 case HOLD:
997 if (container < 0) {
998 fprintf(stderr, "No container found\n");
999 exit(EXIT_FAILURE);
1000 }
1001 file_off += ALIGN(img_sp->entry, sector_size);
1002 break;
1003
Peng Fan60a56072018-10-16 04:50:30 +00001004 case SECO:
Peng Faneeb23bf2022-07-26 16:41:19 +08001005 case SENTINEL:
Peng Fanf107b0f2018-11-05 09:53:28 +00001006 if (container < 0) {
1007 fprintf(stderr, "No container found\n");
1008 exit(EXIT_FAILURE);
1009 }
Peng Fan60a56072018-10-16 04:50:30 +00001010 check_file(&sbuf, img_sp->filename);
1011 tmp_filename = img_sp->filename;
1012 set_image_array_entry(&imx_header.fhdr[container],
1013 soc,
1014 img_sp,
1015 file_off,
1016 sbuf.st_size,
1017 tmp_filename, dcd_skip);
1018 img_sp->src = file_off;
1019
1020 file_off += sbuf.st_size;
Peng Fan60a56072018-10-16 04:50:30 +00001021 break;
1022
1023 case NEW_CONTAINER:
1024 container++;
1025 set_container(&imx_header.fhdr[container], sw_version,
1026 CONTAINER_ALIGNMENT,
1027 CONTAINER_FLAGS_DEFAULT,
1028 fuse_version);
Peng Fan60a56072018-10-16 04:50:30 +00001029 scfw_flags = 0;
1030 break;
1031
1032 case APPEND:
1033 /*
1034 * nothing to do here, the container is appended
1035 * in the output
1036 */
1037 break;
1038 case FLAG:
1039 /*
1040 * override the flags for scfw in current container
1041 * mask off bottom 16 bits.
1042 */
1043 scfw_flags = img_sp->entry & 0xFFFF0000;
1044 break;
1045 case FILEOFF:
1046 if (file_off > img_sp->dst) {
1047 fprintf(stderr, "FILEOFF address less than current file offset!!!\n");
1048 exit(EXIT_FAILURE);
1049 }
1050 if (img_sp->dst != ALIGN(img_sp->dst, sector_size)) {
1051 fprintf(stderr, "FILEOFF address is not aligned to sector size!!!\n");
1052 exit(EXIT_FAILURE);
1053 }
1054 file_off = img_sp->dst;
1055 break;
1056 case PARTITION:
1057 /*
1058 * keep custom partition until next executable image
1059 * use a global var for default behaviour
1060 */
1061 custom_partition = img_sp->entry;
1062 break;
1063 default:
1064 fprintf(stderr, "unrecognized option in input stack (%d)\n", img_sp->option);
1065 exit(EXIT_FAILURE);
1066 }
1067 img_sp++; /* advance index */
1068 }
1069
1070 /* Append container (if specified) */
1071 img_sp = image_stack;
1072 do {
1073 if (img_sp->option == APPEND) {
1074 copy_file(ofd, img_sp->filename, 0, 0);
Alice Guocd759f32025-04-28 18:37:40 +08001075 if (v2x)
1076 file_padding += FIRST_CONTAINER_HEADER_LENGTH * 2;
1077 else
1078 file_padding += FIRST_CONTAINER_HEADER_LENGTH;
Peng Fan60a56072018-10-16 04:50:30 +00001079 }
1080 img_sp++;
1081 } while (img_sp->option != NO_IMG);
1082
Alice Guocd759f32025-04-28 18:37:40 +08001083 fprintf(stderr, "%s: %x %d\n", __func__, file_padding, v2x);
Peng Fan60a56072018-10-16 04:50:30 +00001084 /* Add padding or skip appended container */
Peng Fan00c2dd52018-11-05 09:53:22 +00001085 ret = lseek(ofd, file_padding, SEEK_SET);
1086 if (ret < 0) {
1087 fprintf(stderr, "%s: lseek error %s\n",
1088 __func__, strerror(errno));
1089 exit(EXIT_FAILURE);
1090 }
Peng Fan60a56072018-10-16 04:50:30 +00001091
Peng Fan18864852018-11-05 09:53:31 +00001092 if (container >= 0) {
1093 /* Note: Image offset are not contained in the image */
1094 tmp = flatten_container_header(&imx_header, container + 1,
1095 &size, file_padding);
Alice Guocd759f32025-04-28 18:37:40 +08001096 fprintf(stderr, "error writing image hdr %x\n", size);
Peng Fan18864852018-11-05 09:53:31 +00001097 /* Write image header */
1098 if (write(ofd, tmp, size) != size) {
1099 fprintf(stderr, "error writing image hdr\n");
1100 exit(EXIT_FAILURE);
1101 }
Peng Fan60a56072018-10-16 04:50:30 +00001102
Peng Fan18864852018-11-05 09:53:31 +00001103 /* Clean-up memory used by the headers */
1104 free(tmp);
1105 }
Peng Fan60a56072018-10-16 04:50:30 +00001106
1107 /*
1108 * step through the image stack again this time copying
1109 * images to final bin, stop once we reach null terminator.
1110 */
1111 img_sp = image_stack;
1112 while (img_sp->option != NO_IMG) {
1113 if (img_sp->option == M40 || img_sp->option == M41 ||
1114 img_sp->option == AP || img_sp->option == DATA ||
1115 img_sp->option == SCD || img_sp->option == SCFW ||
Peng Faneeb23bf2022-07-26 16:41:19 +08001116 img_sp->option == SECO || img_sp->option == MSG_BLOCK ||
Alice Guocd759f32025-04-28 18:37:40 +08001117 img_sp->option == UPOWER || img_sp->option == SENTINEL ||
1118 img_sp->option == OEI) {
Peng Fan60a56072018-10-16 04:50:30 +00001119 copy_file_aligned(ofd, img_sp->filename, img_sp->src,
1120 sector_size);
1121 }
1122 img_sp++;
1123 }
1124
1125 return 0;
1126}
1127
1128int imx8image_copy_image(int outfd, struct image_tool_params *mparams)
1129{
1130 image_t *img_sp = param_stack;
1131
1132 /*
1133 * SECO FW is a container image, this is to calculate the
1134 * 2nd container offset.
1135 */
1136 fprintf(stdout, "parsing %s\n", mparams->imagename);
1137 parse_cfg_file(img_sp, mparams->imagename);
1138
1139 if (sector_size == 0) {
1140 fprintf(stderr, "Wrong sector size\n");
1141 exit(EXIT_FAILURE);
1142 }
1143
1144 fprintf(stdout, "CONTAINER Sector size:\t%08x\n", sector_size);
1145 fprintf(stdout, "CONTAINER FUSE VERSION:\t0x%02x\n", fuse_version);
1146 fprintf(stdout, "CONTAINER SW VERSION:\t0x%04x\n", sw_version);
1147
1148 build_container(soc, sector_size, emmc_fastboot,
Alice Guo89099b32025-06-24 18:09:22 +08001149 img_sp, dcd_skip, fuse_version, sw_version, outfd);
Peng Fan60a56072018-10-16 04:50:30 +00001150
1151 return 0;
1152}
1153
1154/*
1155 * imx8image parameters
1156 */
1157U_BOOT_IMAGE_TYPE(
1158 imx8image,
1159 "NXP i.MX8 Boot Image support",
1160 0,
1161 NULL,
1162 imx8image_check_params,
1163 NULL,
1164 imx8image_print_header,
1165 imx8image_set_header,
1166 NULL,
1167 imx8image_check_image_types,
1168 NULL,
1169 NULL
1170);