1 // SPDX-License-Identifier: GPL-2.0+
5 * Peng Fan <peng.fan@nxp.com>
12 static int sector_size
;
13 static soc_type_t soc
;
14 static int container
= -1;
15 static int32_t core_type
= CFG_CORE_INVALID
;
16 static bool emmc_fastboot
;
17 static image_t param_stack
[IMG_STACK_SIZE
];
18 static uint8_t fuse_version
;
19 static uint16_t sw_version
;
20 static uint32_t custom_partition
;
21 static uint32_t scfw_flags
;
23 int imx8image_check_params(struct image_tool_params
*params
)
28 static void imx8image_set_header(void *ptr
, struct stat
*sbuf
, int ifd
,
29 struct image_tool_params
*params
)
33 static void imx8image_print_header(const void *ptr
, struct image_tool_params
*params
)
37 static int imx8image_check_image_types(uint8_t type
)
39 return (type
== IH_TYPE_IMX8IMAGE
) ? EXIT_SUCCESS
: EXIT_FAILURE
;
42 static table_entry_t imx8image_cmds
[] = {
43 {CMD_BOOT_FROM
, "BOOT_FROM", "boot command", },
44 {CMD_FUSE_VERSION
, "FUSE_VERSION", "fuse version", },
45 {CMD_SW_VERSION
, "SW_VERSION", "sw version", },
46 {CMD_MSG_BLOCK
, "MSG_BLOCK", "msg block", },
47 {CMD_FILEOFF
, "FILEOFF", "fileoff", },
48 {CMD_FLAG
, "FLAG", "flag", },
49 {CMD_APPEND
, "APPEND", "append a container", },
50 {CMD_PARTITION
, "PARTITION", "new partition", },
51 {CMD_SOC_TYPE
, "SOC_TYPE", "soc type", },
52 {CMD_CONTAINER
, "CONTAINER", "new container", },
53 {CMD_IMAGE
, "IMAGE", "new image", },
54 {CMD_DATA
, "DATA", "new data", },
58 static table_entry_t imx8image_core_entries
[] = {
59 {CFG_SCU
, "SCU", "scu core", },
60 {CFG_M40
, "M40", "M4 core 0", },
61 {CFG_M41
, "M41", "M4 core 1", },
62 {CFG_A35
, "A35", "A35 core", },
63 {CFG_A55
, "A55", "A55 core", },
64 {CFG_A53
, "A53", "A53 core", },
65 {CFG_A72
, "A72", "A72 core", },
69 static table_entry_t imx8image_sector_size
[] = {
70 {0x400, "sd", "sd/emmc",},
71 {0x400, "emmc_fastboot", "emmc fastboot",},
72 {0x400, "fspi", "flexspi", },
73 {0x1000, "nand_4k", "nand 4K", },
74 {0x2000, "nand_8k", "nand 8K", },
75 {0x4000, "nand_16k", "nand 16K", },
76 {-1, "", "Invalid", },
79 static void parse_cfg_cmd(image_t
*param_stack
, int32_t cmd
, char *token
,
80 char *name
, int lineno
)
84 sector_size
= get_table_entry_id(imx8image_sector_size
,
85 "imximage boot option",
87 if (!strncmp("emmc_fastboot", token
, 13))
90 case CMD_FUSE_VERSION
:
91 fuse_version
= (uint8_t)(strtoll(token
, NULL
, 0) & 0xFF);
94 sw_version
= (uint8_t)(strtoll(token
, NULL
, 0) & 0xFFFF);
97 param_stack
[p_idx
].option
= FILEOFF
;
98 param_stack
[p_idx
++].dst
= (uint32_t)strtoll(token
, NULL
, 0);
101 param_stack
[p_idx
].option
= MSG_BLOCK
;
102 param_stack
[p_idx
].filename
= token
;
105 param_stack
[p_idx
].option
= FLAG
;
106 param_stack
[p_idx
++].entry
= (uint32_t)strtoll(token
, NULL
, 0);
109 param_stack
[p_idx
].option
= APPEND
;
110 param_stack
[p_idx
++].filename
= token
;
113 param_stack
[p_idx
].option
= PARTITION
;
114 param_stack
[p_idx
++].entry
= (uint32_t)strtoll(token
, NULL
, 0);
117 if (!strncmp(token
, "IMX8QX", 6)) {
119 } else if (!strncmp(token
, "IMX8QM", 6)) {
121 } else if (!strncmp(token
, "ULP", 3)) {
123 } else if (!strncmp(token
, "IMX9", 4)) {
126 fprintf(stderr
, "Unknown CMD_SOC_TYPE");
132 core_type
= get_table_entry_id(imx8image_core_entries
,
133 "imx8image core entries",
136 fprintf(stderr
, "Wrong IMAGE core_type %s\n", token
);
145 static void parse_cfg_fld(image_t
*param_stack
, int32_t *cmd
, char *token
,
146 char *name
, int lineno
, int fld
)
150 *cmd
= get_table_entry_id(imx8image_cmds
, "imx8image cmds",
153 fprintf(stderr
, "Error: %s[%d] - Invalid command (%s)\n", name
, lineno
, token
);
157 if (*cmd
== CMD_CONTAINER
) {
158 fprintf(stdout
, "New Container: \t%d\n", ++container
);
159 param_stack
[p_idx
++].option
= NEW_CONTAINER
;
163 parse_cfg_cmd(param_stack
, *cmd
, token
, name
, lineno
);
166 if (*cmd
== CMD_MSG_BLOCK
) {
167 if (!strncmp(token
, "fuse", 4)) {
168 param_stack
[p_idx
].ext
= SC_R_OTP
;
169 } else if (!strncmp(token
, "debug", 5)) {
170 param_stack
[p_idx
].ext
= SC_R_DEBUG
;
171 } else if (!strncmp(token
, "field", 5)) {
172 param_stack
[p_idx
].ext
= SC_R_ROM_0
;
174 fprintf(stderr
, "MSG type not found %s\n", token
);
181 param_stack
[p_idx
].option
= SCFW
;
182 param_stack
[p_idx
++].filename
= token
;
185 param_stack
[p_idx
].option
= M40
;
186 param_stack
[p_idx
].ext
= 0;
187 param_stack
[p_idx
].filename
= token
;
190 param_stack
[p_idx
].option
= M41
;
191 param_stack
[p_idx
].ext
= 1;
192 param_stack
[p_idx
].filename
= token
;
196 param_stack
[p_idx
].ext
= CORE_CA35
;
197 param_stack
[p_idx
].option
=
198 (*cmd
== CMD_DATA
) ? DATA
: AP
;
199 param_stack
[p_idx
].filename
= token
;
202 param_stack
[p_idx
].ext
= CORE_CA53
;
203 param_stack
[p_idx
].option
=
204 (*cmd
== CMD_DATA
) ? DATA
: AP
;
205 param_stack
[p_idx
].filename
= token
;
208 param_stack
[p_idx
].ext
= CORE_CA72
;
209 param_stack
[p_idx
].option
=
210 (*cmd
== CMD_DATA
) ? DATA
: AP
;
211 param_stack
[p_idx
].filename
= token
;
216 if (*cmd
== CMD_MSG_BLOCK
) {
217 param_stack
[p_idx
++].entry
=
218 (uint32_t)strtoll(token
, NULL
, 0);
230 param_stack
[p_idx
++].entry
=
231 (uint32_t)strtoll(token
, NULL
, 0);
239 static uint32_t parse_cfg_file(image_t
*param_stack
, char *name
)
243 char *token
, *saveptr1
, *saveptr2
;
249 fd
= fopen(name
, "r");
251 fprintf(stderr
, "Error: %s - Can't open cfg file\n", name
);
256 * Very simple parsing, line starting with # are comments
259 while ((getline(&line
, &len
, fd
)) > 0) {
262 token
= strtok_r(line
, "\r\n", &saveptr1
);
266 /* Check inside the single line */
267 for (fld
= CFG_COMMAND
, cmd
= CFG_INVALID
,
268 line
= token
; ; line
= NULL
, fld
++) {
269 token
= strtok_r(line
, " \t", &saveptr2
);
273 /* Drop all text starting with '#' as comments */
277 parse_cfg_fld(param_stack
, &cmd
, token
, name
, lineno
,
286 static void check_file(struct stat
*sbuf
, char *filename
)
288 int tmp_fd
= open(filename
, O_RDONLY
| O_BINARY
);
291 fprintf(stderr
, "%s: Can't open: %s\n",
292 filename
, strerror(errno
));
296 if (fstat(tmp_fd
, sbuf
) < 0) {
297 fprintf(stderr
, "%s: Can't stat: %s\n",
298 filename
, strerror(errno
));
305 static void copy_file_aligned(int ifd
, const char *datafile
, int offset
,
311 uint8_t zeros
[0x4000];
315 if (align
> 0x4000) {
316 fprintf(stderr
, "Wrong alignment requested %d\n", align
);
320 memset(zeros
, 0, sizeof(zeros
));
322 dfd
= open(datafile
, O_RDONLY
| O_BINARY
);
324 fprintf(stderr
, "Can't open %s: %s\n",
325 datafile
, strerror(errno
));
329 if (fstat(dfd
, &sbuf
) < 0) {
330 fprintf(stderr
, "Can't stat %s: %s\n",
331 datafile
, strerror(errno
));
335 if (sbuf
.st_size
== 0)
338 ptr
= mmap(0, sbuf
.st_size
, PROT_READ
, MAP_SHARED
, dfd
, 0);
339 if (ptr
== MAP_FAILED
) {
340 fprintf(stderr
, "Can't read %s: %s\n",
341 datafile
, strerror(errno
));
346 ret
= lseek(ifd
, offset
, SEEK_SET
);
348 fprintf(stderr
, "%s: lseek error %s\n",
349 __func__
, strerror(errno
));
353 if (write(ifd
, ptr
, size
) != size
) {
354 fprintf(stderr
, "Write error %s\n", strerror(errno
));
358 align
= ALIGN(size
, align
) - size
;
360 if (write(ifd
, (char *)&zeros
, align
) != align
) {
361 fprintf(stderr
, "Write error: %s\n", strerror(errno
));
365 munmap((void *)ptr
, sbuf
.st_size
);
370 static void copy_file (int ifd
, const char *datafile
, int pad
, int offset
)
380 memset(zeros
, 0, sizeof(zeros
));
382 dfd
= open(datafile
, O_RDONLY
| O_BINARY
);
384 fprintf(stderr
, "Can't open %s: %s\n",
385 datafile
, strerror(errno
));
389 if (fstat(dfd
, &sbuf
) < 0) {
390 fprintf(stderr
, "Can't stat %s: %s\n",
391 datafile
, strerror(errno
));
395 if (sbuf
.st_size
== 0)
398 ptr
= mmap(0, sbuf
.st_size
, PROT_READ
, MAP_SHARED
, dfd
, 0);
399 if (ptr
== MAP_FAILED
) {
400 fprintf(stderr
, "Can't read %s: %s\n",
401 datafile
, strerror(errno
));
406 ret
= lseek(ifd
, offset
, SEEK_SET
);
408 fprintf(stderr
, "%s: lseek error %s\n",
409 __func__
, strerror(errno
));
413 if (write(ifd
, ptr
, size
) != size
) {
414 fprintf(stderr
, "Write error %s\n",
421 if (pad
== 1 && tail
!= 0) {
422 if (write(ifd
, (char *)&zero
, 4 - tail
) != 4 - tail
) {
423 fprintf(stderr
, "Write error on %s\n",
427 } else if (pad
> 1) {
429 int todo
= sizeof(zeros
);
433 if (write(ifd
, (char *)&zeros
, todo
) != todo
) {
434 fprintf(stderr
, "Write error: %s\n",
442 munmap((void *)ptr
, sbuf
.st_size
);
447 uint64_t read_dcd_offset(char *filename
)
454 dfd
= open(filename
, O_RDONLY
| O_BINARY
);
456 fprintf(stderr
, "Can't open %s: %s\n", filename
, strerror(errno
));
460 if (fstat(dfd
, &sbuf
) < 0) {
461 fprintf(stderr
, "Can't stat %s: %s\n", filename
, strerror(errno
));
465 ptr
= mmap(0, sbuf
.st_size
, PROT_READ
, MAP_SHARED
, dfd
, 0);
466 if (ptr
== MAP_FAILED
) {
467 fprintf(stderr
, "Can't read %s: %s\n", filename
, strerror(errno
));
471 offset
= *(uint32_t *)(ptr
+ DCD_ENTRY_ADDR_IN_SCFW
);
473 munmap((void *)ptr
, sbuf
.st_size
);
479 static void set_image_hash(boot_img_t
*img
, char *filename
, uint32_t hash_type
)
482 char sha_command
[512];
483 char hash
[2 * HASH_MAX_LEN
+ 1];
487 sprintf(sha_command
, "sha%dsum /dev/null", hash_type
);
489 sprintf(sha_command
, "dd if=/dev/zero of=tmp_pad bs=%d count=1;\
490 dd if=\'%s\' of=tmp_pad conv=notrunc;\
491 sha%dsum tmp_pad; rm -f tmp_pad",
492 img
->size
, filename
, hash_type
);
495 case HASH_TYPE_SHA_256
:
496 img
->hab_flags
|= IMG_FLAG_HASH_SHA256
;
498 case HASH_TYPE_SHA_384
:
499 img
->hab_flags
|= IMG_FLAG_HASH_SHA384
;
501 case HASH_TYPE_SHA_512
:
502 img
->hab_flags
|= IMG_FLAG_HASH_SHA512
;
505 fprintf(stderr
, "Wrong hash type selected (%d) !!!\n\n",
510 memset(img
->hash
, 0, HASH_MAX_LEN
);
512 fp
= popen(sha_command
, "r");
514 fprintf(stderr
, "Failed to run command hash\n");
518 if (!fgets(hash
, hash_type
/ 4 + 1, fp
)) {
519 fprintf(stderr
, "Failed to hash file: %s\n", filename
);
523 for (i
= 0; i
< strlen(hash
) / 2; i
++) {
524 ret
= sscanf(hash
+ 2 * i
, "%02hhx", &img
->hash
[i
]);
526 fprintf(stderr
, "Failed sscanf hash: %d\n", ret
);
534 static void set_image_array_entry(flash_header_v3_t
*container
,
535 soc_type_t soc
, const image_t
*image_stack
,
536 uint32_t offset
, uint32_t size
,
537 char *tmp_filename
, bool dcd_skip
)
539 uint64_t entry
= image_stack
->entry
;
540 uint64_t core
= image_stack
->ext
;
543 option_type_t type
= image_stack
->option
;
544 boot_img_t
*img
= &container
->img
[container
->num_images
];
546 img
->offset
= offset
; /* Is re-adjusted later */
549 set_image_hash(img
, tmp_filename
, IMAGE_HASH_ALGO_DEFAULT
);
553 img
->hab_flags
|= IMG_TYPE_SECO
;
554 img
->hab_flags
|= CORE_SECO
<< BOOT_IMG_FLAGS_CORE_SHIFT
;
556 img
->dst
= 0x20C00000;
557 img
->entry
= 0x20000000;
560 if (container
->num_images
> 0) {
561 fprintf(stderr
, "Error: SENTINEL container only allows 1 image\n");
565 img
->hab_flags
|= IMG_TYPE_SENTINEL
;
566 img
->hab_flags
|= CORE_ULP_SENTINEL
<< BOOT_IMG_FLAGS_CORE_SHIFT
;
567 tmp_name
= "SENTINEL";
568 img
->dst
= 0xe4000000; /* S400 IRAM base */
569 img
->entry
= 0xe4000000;
572 if (soc
== QX
&& core
== CORE_CA35
) {
573 meta
= IMAGE_A35_DEFAULT_META(custom_partition
);
574 } else if (soc
== QM
&& core
== CORE_CA53
) {
575 meta
= IMAGE_A53_DEFAULT_META(custom_partition
);
576 } else if (soc
== QM
&& core
== CORE_CA72
) {
577 meta
= IMAGE_A72_DEFAULT_META(custom_partition
);
578 } else if (((soc
== ULP
) || (soc
== IMX9
)) && core
== CORE_CA35
) {
582 "Error: invalid AP core id: %" PRIu64
"\n",
586 img
->hab_flags
|= IMG_TYPE_EXEC
;
587 if ((soc
== ULP
) || (soc
== IMX9
))
588 img
->hab_flags
|= CORE_ULP_CA35
<< BOOT_IMG_FLAGS_CORE_SHIFT
;
590 img
->hab_flags
|= CORE_CA53
<< BOOT_IMG_FLAGS_CORE_SHIFT
; /* On B0, only core id = 4 is valid */
595 custom_partition
= 0;
599 if ((soc
== ULP
) || (soc
== IMX9
)) {
600 core
= CORE_ULP_CM33
;
605 meta
= IMAGE_M4_0_DEFAULT_META(custom_partition
);
606 } else if (core
== 1) {
608 meta
= IMAGE_M4_1_DEFAULT_META(custom_partition
);
611 "Error: invalid m4 core id: %" PRIu64
"\n",
616 img
->hab_flags
|= IMG_TYPE_EXEC
;
617 img
->hab_flags
|= core
<< BOOT_IMG_FLAGS_CORE_SHIFT
;
619 if ((entry
& 0x7) != 0) {
620 fprintf(stderr
, "\n\nWarning: M4 Destination address is not 8 byte aligned\n\n");
626 custom_partition
= 0;
629 img
->hab_flags
|= IMG_TYPE_DATA
;
630 if ((soc
== ULP
) || (soc
== IMX9
)) {
631 if (core
== CORE_CM4_0
)
632 img
->hab_flags
|= CORE_ULP_CM33
<< BOOT_IMG_FLAGS_CORE_SHIFT
;
634 img
->hab_flags
|= CORE_ULP_CA35
<< BOOT_IMG_FLAGS_CORE_SHIFT
;
636 img
->hab_flags
|= CORE_CA35
<< BOOT_IMG_FLAGS_CORE_SHIFT
;
642 img
->hab_flags
|= IMG_TYPE_DATA
;
643 img
->hab_flags
|= CORE_CA35
<< BOOT_IMG_FLAGS_CORE_SHIFT
;
644 img
->meta
= core
<< BOOT_IMG_META_MU_RID_SHIFT
;
645 tmp_name
= "MSG_BLOCK";
649 img
->hab_flags
|= scfw_flags
& 0xFFFF0000;
650 img
->hab_flags
|= IMG_TYPE_EXEC
;
651 img
->hab_flags
|= CORE_SC
<< BOOT_IMG_FLAGS_CORE_SHIFT
;
653 img
->dst
= 0x1FFE0000;
654 img
->entry
= 0x1FFE0000;
656 /* Lets add the DCD now */
658 container
->num_images
++;
659 img
= &container
->img
[container
->num_images
];
660 img
->hab_flags
|= IMG_TYPE_DCD_DDR
;
661 img
->hab_flags
|= CORE_SC
<< BOOT_IMG_FLAGS_CORE_SHIFT
;
662 set_image_hash(img
, "/dev/null",
663 IMAGE_HASH_ALGO_DEFAULT
);
664 img
->offset
= offset
+ img
->size
;
665 img
->entry
= read_dcd_offset(tmp_filename
);
666 img
->dst
= img
->entry
- 1;
671 img
->hab_flags
|= IMG_TYPE_EXEC
;
672 img
->hab_flags
|= CORE_ULP_UPOWER
<< BOOT_IMG_FLAGS_CORE_SHIFT
;
674 img
->dst
= 0x28300200; /* UPOWER code RAM */
675 img
->entry
= 0x28300200;
679 fprintf(stderr
, "unrecognized image type (%d)\n", type
);
683 fprintf(stdout
, "%s file_offset = 0x%x size = 0x%x\n", tmp_name
, offset
, size
);
685 container
->num_images
++;
688 void set_container(flash_header_v3_t
*container
, uint16_t sw_version
,
689 uint32_t alignment
, uint32_t flags
, uint16_t fuse_version
)
691 container
->sig_blk_hdr
.tag
= 0x90;
692 container
->sig_blk_hdr
.length
= sizeof(sig_blk_hdr_t
);
693 container
->sw_version
= sw_version
;
694 container
->padding
= alignment
;
695 container
->fuse_version
= fuse_version
;
696 container
->flags
= flags
;
697 fprintf(stdout
, "container flags: 0x%x\n", container
->flags
);
700 static int get_container_image_start_pos(image_t
*image_stack
, uint32_t align
)
702 image_t
*img_sp
= image_stack
;
703 /*8K total container header*/
704 int file_off
= CONTAINER_IMAGE_ARRAY_START_OFFSET
;
706 flash_header_v3_t header
;
709 while (img_sp
->option
!= NO_IMG
) {
710 if (img_sp
->option
== APPEND
) {
711 fd
= fopen(img_sp
->filename
, "r");
713 fprintf(stderr
, "Fail open first container file %s\n", img_sp
->filename
);
717 ret
= fread(&header
, sizeof(header
), 1, fd
);
719 printf("Failure Read header %d\n", ret
);
725 if (header
.tag
!= IVT_HEADER_TAG_B0
) {
726 fprintf(stderr
, "header tag mismatched \n");
730 header
.img
[header
.num_images
- 1].size
;
731 file_off
= ALIGN(file_off
, align
);
741 static void set_imx_hdr_v3(imx_header_v3_t
*imxhdr
, uint32_t cont_id
)
743 flash_header_v3_t
*fhdr_v3
= &imxhdr
->fhdr
[cont_id
];
745 /* Set magic number, Only >= B0 supported */
746 fhdr_v3
->tag
= IVT_HEADER_TAG_B0
;
747 fhdr_v3
->version
= IVT_VERSION_B0
;
750 static uint8_t *flatten_container_header(imx_header_v3_t
*imx_header
,
751 uint8_t containers_count
,
753 uint32_t file_offset
)
755 uint8_t *flat
= NULL
;
760 /* Compute size of all container headers */
761 for (i
= 0; i
< containers_count
; i
++) {
762 flash_header_v3_t
*container
= &imx_header
->fhdr
[i
];
764 container
->sig_blk_offset
= HEADER_IMG_ARRAY_OFFSET
+
765 container
->num_images
* IMG_ARRAY_ENTRY_SIZE
;
767 container
->length
= HEADER_IMG_ARRAY_OFFSET
+
768 (IMG_ARRAY_ENTRY_SIZE
* container
->num_images
) +
769 sizeof(sig_blk_hdr_t
);
771 /* Print info needed by CST to sign the container header */
772 fprintf(stdout
, "CST: CONTAINER %d offset: 0x%x\n",
773 i
, file_offset
+ size
);
774 fprintf(stdout
, "CST: CONTAINER %d: Signature Block: offset is at 0x%x\n", i
,
775 file_offset
+ size
+ container
->length
-
776 SIGNATURE_BLOCK_HEADER_LENGTH
);
778 size
+= ALIGN(container
->length
, container
->padding
);
781 flat
= calloc(size
, sizeof(uint8_t));
783 fprintf(stderr
, "Failed to allocate memory (%d)\n", size
);
790 for (i
= 0; i
< containers_count
; i
++) {
791 flash_header_v3_t
*container
= &imx_header
->fhdr
[i
];
792 uint32_t container_start_offset
= ptr
- flat
;
794 /* Append container header */
795 append(ptr
, container
, HEADER_IMG_ARRAY_OFFSET
);
797 /* Adjust images offset to start from container headers start */
798 for (j
= 0; j
< container
->num_images
; j
++) {
799 container
->img
[j
].offset
-=
800 container_start_offset
+ file_offset
;
802 /* Append each image array entry */
803 for (j
= 0; j
< container
->num_images
; j
++)
804 append(ptr
, &container
->img
[j
], sizeof(boot_img_t
));
806 append(ptr
, &container
->sig_blk_hdr
, sizeof(sig_blk_hdr_t
));
808 /* Padding for container (if necessary) */
809 ptr
+= ALIGN(container
->length
, container
->padding
) -
816 static int build_container(soc_type_t soc
, uint32_t sector_size
,
817 bool emmc_fastboot
, image_t
*image_stack
,
818 bool dcd_skip
, uint8_t fuse_version
,
819 uint16_t sw_version
, int ofd
)
821 static imx_header_v3_t imx_header
;
822 image_t
*img_sp
= image_stack
;
826 char *tmp_filename
= NULL
;
828 uint32_t file_padding
= 0;
833 memset((char *)&imx_header
, 0, sizeof(imx_header_v3_t
));
836 fprintf(stderr
, "Empty image stack ");
841 fprintf(stdout
, "Platform:\ti.MX8QXP B0\n");
843 fprintf(stdout
, "Platform:\ti.MX8QM B0\n");
845 fprintf(stdout
, "Platform:\ti.MX8ULP A0\n");
846 else if (soc
== IMX9
)
847 fprintf(stdout
, "Platform:\ti.MX9\n");
849 set_imx_hdr_v3(&imx_header
, 0);
850 set_imx_hdr_v3(&imx_header
, 1);
852 file_off
= get_container_image_start_pos(image_stack
, sector_size
);
853 fprintf(stdout
, "container image offset (aligned):%x\n", file_off
);
855 /* step through image stack and generate the header */
856 img_sp
= image_stack
;
858 /* stop once we reach null terminator */
859 while (img_sp
->option
!= NO_IMG
) {
860 switch (img_sp
->option
) {
869 fprintf(stderr
, "No container found\n");
872 check_file(&sbuf
, img_sp
->filename
);
873 tmp_filename
= img_sp
->filename
;
874 set_image_array_entry(&imx_header
.fhdr
[container
],
875 soc
, img_sp
, file_off
,
876 ALIGN(sbuf
.st_size
, sector_size
),
877 tmp_filename
, dcd_skip
);
878 img_sp
->src
= file_off
;
880 file_off
+= ALIGN(sbuf
.st_size
, sector_size
);
886 fprintf(stderr
, "No container found\n");
889 check_file(&sbuf
, img_sp
->filename
);
890 tmp_filename
= img_sp
->filename
;
891 set_image_array_entry(&imx_header
.fhdr
[container
],
896 tmp_filename
, dcd_skip
);
897 img_sp
->src
= file_off
;
899 file_off
+= sbuf
.st_size
;
904 set_container(&imx_header
.fhdr
[container
], sw_version
,
906 CONTAINER_FLAGS_DEFAULT
,
913 * nothing to do here, the container is appended
919 * override the flags for scfw in current container
920 * mask off bottom 16 bits.
922 scfw_flags
= img_sp
->entry
& 0xFFFF0000;
925 if (file_off
> img_sp
->dst
) {
926 fprintf(stderr
, "FILEOFF address less than current file offset!!!\n");
929 if (img_sp
->dst
!= ALIGN(img_sp
->dst
, sector_size
)) {
930 fprintf(stderr
, "FILEOFF address is not aligned to sector size!!!\n");
933 file_off
= img_sp
->dst
;
937 * keep custom partition until next executable image
938 * use a global var for default behaviour
940 custom_partition
= img_sp
->entry
;
943 fprintf(stderr
, "unrecognized option in input stack (%d)\n", img_sp
->option
);
946 img_sp
++; /* advance index */
949 /* Append container (if specified) */
950 img_sp
= image_stack
;
952 if (img_sp
->option
== APPEND
) {
953 copy_file(ofd
, img_sp
->filename
, 0, 0);
954 file_padding
+= FIRST_CONTAINER_HEADER_LENGTH
;
957 } while (img_sp
->option
!= NO_IMG
);
959 /* Add padding or skip appended container */
960 ret
= lseek(ofd
, file_padding
, SEEK_SET
);
962 fprintf(stderr
, "%s: lseek error %s\n",
963 __func__
, strerror(errno
));
967 if (container
>= 0) {
968 /* Note: Image offset are not contained in the image */
969 tmp
= flatten_container_header(&imx_header
, container
+ 1,
970 &size
, file_padding
);
971 /* Write image header */
972 if (write(ofd
, tmp
, size
) != size
) {
973 fprintf(stderr
, "error writing image hdr\n");
977 /* Clean-up memory used by the headers */
982 * step through the image stack again this time copying
983 * images to final bin, stop once we reach null terminator.
985 img_sp
= image_stack
;
986 while (img_sp
->option
!= NO_IMG
) {
987 if (img_sp
->option
== M40
|| img_sp
->option
== M41
||
988 img_sp
->option
== AP
|| img_sp
->option
== DATA
||
989 img_sp
->option
== SCD
|| img_sp
->option
== SCFW
||
990 img_sp
->option
== SECO
|| img_sp
->option
== MSG_BLOCK
||
991 img_sp
->option
== UPOWER
|| img_sp
->option
== SENTINEL
) {
992 copy_file_aligned(ofd
, img_sp
->filename
, img_sp
->src
,
1001 int imx8image_copy_image(int outfd
, struct image_tool_params
*mparams
)
1003 image_t
*img_sp
= param_stack
;
1006 * SECO FW is a container image, this is to calculate the
1007 * 2nd container offset.
1009 fprintf(stdout
, "parsing %s\n", mparams
->imagename
);
1010 parse_cfg_file(img_sp
, mparams
->imagename
);
1012 if (sector_size
== 0) {
1013 fprintf(stderr
, "Wrong sector size\n");
1017 fprintf(stdout
, "CONTAINER Sector size:\t%08x\n", sector_size
);
1018 fprintf(stdout
, "CONTAINER FUSE VERSION:\t0x%02x\n", fuse_version
);
1019 fprintf(stdout
, "CONTAINER SW VERSION:\t0x%04x\n", sw_version
);
1021 build_container(soc
, sector_size
, emmc_fastboot
,
1022 img_sp
, false, fuse_version
, sw_version
, outfd
);
1028 * imx8image parameters
1032 "NXP i.MX8 Boot Image support",
1035 imx8image_check_params
,
1037 imx8image_print_header
,
1038 imx8image_set_header
,
1040 imx8image_check_image_types
,