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
)
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_A53
, "A53", "A53 core", },
64 {CFG_A72
, "A72", "A72 core", },
68 static table_entry_t imx8image_sector_size
[] = {
69 {0x400, "sd", "sd/emmc",},
70 {0x400, "emmc_fastboot", "emmc fastboot",},
71 {0x400, "fspi", "flexspi", },
72 {0x1000, "nand_4k", "nand 4K", },
73 {0x2000, "nand_8k", "nand 8K", },
74 {0x4000, "nand_16k", "nand 16K", },
75 {-1, "", "Invalid", },
78 static void parse_cfg_cmd(image_t
*param_stack
, int32_t cmd
, char *token
,
79 char *name
, int lineno
)
83 sector_size
= get_table_entry_id(imx8image_sector_size
,
84 "imximage boot option",
86 if (!strncmp("emmc_fastboot", token
, 13))
89 case CMD_FUSE_VERSION
:
90 fuse_version
= (uint8_t)(strtoll(token
, NULL
, 0) & 0xFF);
93 sw_version
= (uint8_t)(strtoll(token
, NULL
, 0) & 0xFFFF);
96 param_stack
[p_idx
].option
= FILEOFF
;
97 param_stack
[p_idx
++].dst
= (uint32_t)strtoll(token
, NULL
, 0);
100 param_stack
[p_idx
].option
= MSG_BLOCK
;
101 param_stack
[p_idx
].filename
= token
;
104 param_stack
[p_idx
].option
= FLAG
;
105 param_stack
[p_idx
++].entry
= (uint32_t)strtoll(token
, NULL
, 0);
108 param_stack
[p_idx
].option
= APPEND
;
109 param_stack
[p_idx
++].filename
= token
;
112 param_stack
[p_idx
].option
= PARTITION
;
113 param_stack
[p_idx
++].entry
= (uint32_t)strtoll(token
, NULL
, 0);
116 if (!strncmp(token
, "IMX8QX", 6)) {
118 } else if (!strncmp(token
, "IMX8QM", 6)) {
121 fprintf(stderr
, "Unknown CMD_SOC_TYPE");
127 core_type
= get_table_entry_id(imx8image_core_entries
,
128 "imx8image core entries",
131 fprintf(stderr
, "Wrong IMAGE core_type %s\n", token
);
140 static void parse_cfg_fld(image_t
*param_stack
, int32_t *cmd
, char *token
,
141 char *name
, int lineno
, int fld
)
145 *cmd
= get_table_entry_id(imx8image_cmds
, "imx8image cmds",
148 fprintf(stderr
, "Error: %s[%d] - Invalid command (%s)\n", name
, lineno
, token
);
152 if (*cmd
== CMD_CONTAINER
) {
153 fprintf(stdout
, "New Container: \t%d\n", ++container
);
154 param_stack
[p_idx
++].option
= NEW_CONTAINER
;
158 parse_cfg_cmd(param_stack
, *cmd
, token
, name
, lineno
);
161 if (*cmd
== CMD_MSG_BLOCK
) {
162 if (!strncmp(token
, "fuse", 4)) {
163 param_stack
[p_idx
].ext
= SC_R_OTP
;
164 } else if (!strncmp(token
, "debug", 5)) {
165 param_stack
[p_idx
].ext
= SC_R_DEBUG
;
166 } else if (!strncmp(token
, "field", 5)) {
167 param_stack
[p_idx
].ext
= SC_R_ROM_0
;
169 fprintf(stderr
, "MSG type not found %s\n", token
);
176 param_stack
[p_idx
].option
= SCFW
;
177 param_stack
[p_idx
++].filename
= token
;
180 param_stack
[p_idx
].option
= M40
;
181 param_stack
[p_idx
].ext
= 0;
182 param_stack
[p_idx
].filename
= token
;
185 param_stack
[p_idx
].option
= M41
;
186 param_stack
[p_idx
].ext
= 1;
187 param_stack
[p_idx
].filename
= token
;
190 param_stack
[p_idx
].ext
= CORE_CA35
;
191 param_stack
[p_idx
].option
=
192 (*cmd
== CMD_DATA
) ? DATA
: AP
;
193 param_stack
[p_idx
].filename
= token
;
196 param_stack
[p_idx
].ext
= CORE_CA53
;
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_CA72
;
203 param_stack
[p_idx
].option
=
204 (*cmd
== CMD_DATA
) ? DATA
: AP
;
205 param_stack
[p_idx
].filename
= token
;
210 if (*cmd
== CMD_MSG_BLOCK
) {
211 param_stack
[p_idx
++].entry
=
212 (uint32_t)strtoll(token
, NULL
, 0);
223 param_stack
[p_idx
++].entry
=
224 (uint32_t)strtoll(token
, NULL
, 0);
232 static uint32_t parse_cfg_file(image_t
*param_stack
, char *name
)
236 char *token
, *saveptr1
, *saveptr2
;
242 fd
= fopen(name
, "r");
244 fprintf(stderr
, "Error: %s - Can't open cfg file\n", name
);
249 * Very simple parsing, line starting with # are comments
252 while ((getline(&line
, &len
, fd
)) > 0) {
255 token
= strtok_r(line
, "\r\n", &saveptr1
);
259 /* Check inside the single line */
260 for (fld
= CFG_COMMAND
, cmd
= CFG_INVALID
,
261 line
= token
; ; line
= NULL
, fld
++) {
262 token
= strtok_r(line
, " \t", &saveptr2
);
266 /* Drop all text starting with '#' as comments */
270 parse_cfg_fld(param_stack
, &cmd
, token
, name
, lineno
,
278 static void check_file(struct stat
*sbuf
, char *filename
)
280 int tmp_fd
= open(filename
, O_RDONLY
| O_BINARY
);
283 fprintf(stderr
, "%s: Can't open: %s\n",
284 filename
, strerror(errno
));
288 if (fstat(tmp_fd
, sbuf
) < 0) {
289 fprintf(stderr
, "%s: Can't stat: %s\n",
290 filename
, strerror(errno
));
297 static void copy_file_aligned(int ifd
, const char *datafile
, int offset
,
303 uint8_t zeros
[0x4000];
307 if (align
> 0x4000) {
308 fprintf(stderr
, "Wrong alignment requested %d\n", align
);
312 memset(zeros
, 0, sizeof(zeros
));
314 dfd
= open(datafile
, O_RDONLY
| O_BINARY
);
316 fprintf(stderr
, "Can't open %s: %s\n",
317 datafile
, strerror(errno
));
321 if (fstat(dfd
, &sbuf
) < 0) {
322 fprintf(stderr
, "Can't stat %s: %s\n",
323 datafile
, strerror(errno
));
327 if (sbuf
.st_size
== 0)
330 ptr
= mmap(0, sbuf
.st_size
, PROT_READ
, MAP_SHARED
, dfd
, 0);
331 if (ptr
== MAP_FAILED
) {
332 fprintf(stderr
, "Can't read %s: %s\n",
333 datafile
, strerror(errno
));
338 ret
= lseek(ifd
, offset
, SEEK_SET
);
340 fprintf(stderr
, "%s: lseek error %s\n",
341 __func__
, strerror(errno
));
345 if (write(ifd
, ptr
, size
) != size
) {
346 fprintf(stderr
, "Write error %s\n", strerror(errno
));
350 align
= ALIGN(size
, align
) - size
;
352 if (write(ifd
, (char *)&zeros
, align
) != align
) {
353 fprintf(stderr
, "Write error: %s\n", strerror(errno
));
357 munmap((void *)ptr
, sbuf
.st_size
);
362 static void copy_file (int ifd
, const char *datafile
, int pad
, int offset
)
372 memset(zeros
, 0, sizeof(zeros
));
374 dfd
= open(datafile
, O_RDONLY
| O_BINARY
);
376 fprintf(stderr
, "Can't open %s: %s\n",
377 datafile
, strerror(errno
));
381 if (fstat(dfd
, &sbuf
) < 0) {
382 fprintf(stderr
, "Can't stat %s: %s\n",
383 datafile
, strerror(errno
));
387 if (sbuf
.st_size
== 0)
390 ptr
= mmap(0, sbuf
.st_size
, PROT_READ
, MAP_SHARED
, dfd
, 0);
391 if (ptr
== MAP_FAILED
) {
392 fprintf(stderr
, "Can't read %s: %s\n",
393 datafile
, strerror(errno
));
398 ret
= lseek(ifd
, offset
, SEEK_SET
);
400 fprintf(stderr
, "%s: lseek error %s\n",
401 __func__
, strerror(errno
));
405 if (write(ifd
, ptr
, size
) != size
) {
406 fprintf(stderr
, "Write error %s\n",
413 if (pad
== 1 && tail
!= 0) {
414 if (write(ifd
, (char *)&zero
, 4 - tail
) != 4 - tail
) {
415 fprintf(stderr
, "Write error on %s\n",
419 } else if (pad
> 1) {
421 int todo
= sizeof(zeros
);
425 if (write(ifd
, (char *)&zeros
, todo
) != todo
) {
426 fprintf(stderr
, "Write error: %s\n",
434 munmap((void *)ptr
, sbuf
.st_size
);
439 uint64_t read_dcd_offset(char *filename
)
446 dfd
= open(filename
, O_RDONLY
| O_BINARY
);
448 fprintf(stderr
, "Can't open %s: %s\n", filename
, strerror(errno
));
452 if (fstat(dfd
, &sbuf
) < 0) {
453 fprintf(stderr
, "Can't stat %s: %s\n", filename
, strerror(errno
));
457 ptr
= mmap(0, sbuf
.st_size
, PROT_READ
, MAP_SHARED
, dfd
, 0);
458 if (ptr
== MAP_FAILED
) {
459 fprintf(stderr
, "Can't read %s: %s\n", filename
, strerror(errno
));
463 offset
= *(uint32_t *)(ptr
+ DCD_ENTRY_ADDR_IN_SCFW
);
465 munmap((void *)ptr
, sbuf
.st_size
);
471 static void set_image_hash(boot_img_t
*img
, char *filename
, uint32_t hash_type
)
474 char sha_command
[512];
475 char hash
[2 * HASH_MAX_LEN
+ 1];
479 sprintf(sha_command
, "sha%dsum /dev/null", hash_type
);
481 sprintf(sha_command
, "dd if=/dev/zero of=tmp_pad bs=%d count=1;\
482 dd if=\'%s\' of=tmp_pad conv=notrunc;\
483 sha%dsum tmp_pad; rm -f tmp_pad",
484 img
->size
, filename
, hash_type
);
487 case HASH_TYPE_SHA_256
:
488 img
->hab_flags
|= IMG_FLAG_HASH_SHA256
;
490 case HASH_TYPE_SHA_384
:
491 img
->hab_flags
|= IMG_FLAG_HASH_SHA384
;
493 case HASH_TYPE_SHA_512
:
494 img
->hab_flags
|= IMG_FLAG_HASH_SHA512
;
497 fprintf(stderr
, "Wrong hash type selected (%d) !!!\n\n",
502 memset(img
->hash
, 0, HASH_MAX_LEN
);
504 fp
= popen(sha_command
, "r");
506 fprintf(stderr
, "Failed to run command hash\n");
510 if (!fgets(hash
, hash_type
/ 4 + 1, fp
)) {
511 fprintf(stderr
, "Failed to hash file: %s\n", filename
);
515 for (i
= 0; i
< strlen(hash
) / 2; i
++) {
516 ret
= sscanf(hash
+ 2 * i
, "%02hhx", &img
->hash
[i
]);
518 fprintf(stderr
, "Failed sscanf hash: %d\n", ret
);
526 static void set_image_array_entry(flash_header_v3_t
*container
,
527 soc_type_t soc
, const image_t
*image_stack
,
528 uint32_t offset
, uint32_t size
,
529 char *tmp_filename
, bool dcd_skip
)
531 uint64_t entry
= image_stack
->entry
;
532 uint64_t core
= image_stack
->ext
;
535 option_type_t type
= image_stack
->option
;
536 boot_img_t
*img
= &container
->img
[container
->num_images
];
538 img
->offset
= offset
; /* Is re-adjusted later */
541 set_image_hash(img
, tmp_filename
, IMAGE_HASH_ALGO_DEFAULT
);
545 img
->hab_flags
|= IMG_TYPE_SECO
;
546 img
->hab_flags
|= CORE_SECO
<< BOOT_IMG_FLAGS_CORE_SHIFT
;
548 img
->dst
= 0x20C00000;
549 img
->entry
= 0x20000000;
552 if (soc
== QX
&& core
== CORE_CA35
) {
553 meta
= IMAGE_A35_DEFAULT_META(custom_partition
);
554 } else if (soc
== QM
&& core
== CORE_CA53
) {
555 meta
= IMAGE_A53_DEFAULT_META(custom_partition
);
556 } else if (soc
== QM
&& core
== CORE_CA72
) {
557 meta
= IMAGE_A72_DEFAULT_META(custom_partition
);
560 "Error: invalid AP core id: %" PRIu64
"\n",
564 img
->hab_flags
|= IMG_TYPE_EXEC
;
565 /* On B0, only core id = 4 is valid */
566 img
->hab_flags
|= CORE_CA53
<< BOOT_IMG_FLAGS_CORE_SHIFT
;
571 custom_partition
= 0;
577 meta
= IMAGE_M4_0_DEFAULT_META(custom_partition
);
578 } else if (core
== 1) {
580 meta
= IMAGE_M4_1_DEFAULT_META(custom_partition
);
583 "Error: invalid m4 core id: %" PRIu64
"\n",
587 img
->hab_flags
|= IMG_TYPE_EXEC
;
588 img
->hab_flags
|= core
<< BOOT_IMG_FLAGS_CORE_SHIFT
;
590 if ((entry
& 0x7) != 0) {
591 fprintf(stderr
, "\n\nWarning: M4 Destination address is not 8 byte aligned\n\n");
597 custom_partition
= 0;
600 img
->hab_flags
|= IMG_TYPE_DATA
;
601 img
->hab_flags
|= CORE_CA35
<< BOOT_IMG_FLAGS_CORE_SHIFT
;
606 img
->hab_flags
|= IMG_TYPE_DATA
;
607 img
->hab_flags
|= CORE_CA35
<< BOOT_IMG_FLAGS_CORE_SHIFT
;
608 img
->meta
= core
<< BOOT_IMG_META_MU_RID_SHIFT
;
609 tmp_name
= "MSG_BLOCK";
613 img
->hab_flags
|= scfw_flags
& 0xFFFF0000;
614 img
->hab_flags
|= IMG_TYPE_EXEC
;
615 img
->hab_flags
|= CORE_SC
<< BOOT_IMG_FLAGS_CORE_SHIFT
;
617 img
->dst
= 0x1FFE0000;
618 img
->entry
= 0x1FFE0000;
620 /* Lets add the DCD now */
622 container
->num_images
++;
623 img
= &container
->img
[container
->num_images
];
624 img
->hab_flags
|= IMG_TYPE_DCD_DDR
;
625 img
->hab_flags
|= CORE_SC
<< BOOT_IMG_FLAGS_CORE_SHIFT
;
626 set_image_hash(img
, "/dev/null",
627 IMAGE_HASH_ALGO_DEFAULT
);
628 img
->offset
= offset
+ img
->size
;
629 img
->entry
= read_dcd_offset(tmp_filename
);
630 img
->dst
= img
->entry
- 1;
634 fprintf(stderr
, "unrecognized image type (%d)\n", type
);
638 fprintf(stdout
, "%s file_offset = 0x%x size = 0x%x\n", tmp_name
, offset
, size
);
640 container
->num_images
++;
643 void set_container(flash_header_v3_t
*container
, uint16_t sw_version
,
644 uint32_t alignment
, uint32_t flags
, uint16_t fuse_version
)
646 container
->sig_blk_hdr
.tag
= 0x90;
647 container
->sig_blk_hdr
.length
= sizeof(sig_blk_hdr_t
);
648 container
->sw_version
= sw_version
;
649 container
->padding
= alignment
;
650 container
->fuse_version
= fuse_version
;
651 container
->flags
= flags
;
652 fprintf(stdout
, "container flags: 0x%x\n", container
->flags
);
655 static int get_container_image_start_pos(image_t
*image_stack
, uint32_t align
)
657 image_t
*img_sp
= image_stack
;
658 /*8K total container header*/
659 int file_off
= CONTAINER_IMAGE_ARRAY_START_OFFSET
;
661 flash_header_v3_t header
;
664 while (img_sp
->option
!= NO_IMG
) {
665 if (img_sp
->option
== APPEND
) {
666 fd
= fopen(img_sp
->filename
, "r");
668 fprintf(stderr
, "Fail open first container file %s\n", img_sp
->filename
);
672 ret
= fread(&header
, sizeof(header
), 1, fd
);
674 printf("Failure Read header %d\n", ret
);
680 if (header
.tag
!= IVT_HEADER_TAG_B0
) {
681 fprintf(stderr
, "header tag mismatched \n");
685 header
.img
[header
.num_images
- 1].size
;
686 file_off
= ALIGN(file_off
, align
);
696 static void set_imx_hdr_v3(imx_header_v3_t
*imxhdr
, uint32_t cont_id
)
698 flash_header_v3_t
*fhdr_v3
= &imxhdr
->fhdr
[cont_id
];
700 /* Set magic number, Only >= B0 supported */
701 fhdr_v3
->tag
= IVT_HEADER_TAG_B0
;
702 fhdr_v3
->version
= IVT_VERSION_B0
;
705 static uint8_t *flatten_container_header(imx_header_v3_t
*imx_header
,
706 uint8_t containers_count
,
708 uint32_t file_offset
)
710 uint8_t *flat
= NULL
;
715 /* Compute size of all container headers */
716 for (i
= 0; i
< containers_count
; i
++) {
717 flash_header_v3_t
*container
= &imx_header
->fhdr
[i
];
719 container
->sig_blk_offset
= HEADER_IMG_ARRAY_OFFSET
+
720 container
->num_images
* IMG_ARRAY_ENTRY_SIZE
;
722 container
->length
= HEADER_IMG_ARRAY_OFFSET
+
723 (IMG_ARRAY_ENTRY_SIZE
* container
->num_images
) +
724 sizeof(sig_blk_hdr_t
);
726 /* Print info needed by CST to sign the container header */
727 fprintf(stdout
, "CST: CONTAINER %d offset: 0x%x\n",
728 i
, file_offset
+ size
);
729 fprintf(stdout
, "CST: CONTAINER %d: Signature Block: offset is at 0x%x\n", i
,
730 file_offset
+ size
+ container
->length
-
731 SIGNATURE_BLOCK_HEADER_LENGTH
);
733 size
+= ALIGN(container
->length
, container
->padding
);
736 flat
= calloc(size
, sizeof(uint8_t));
738 fprintf(stderr
, "Failed to allocate memory (%d)\n", size
);
745 for (i
= 0; i
< containers_count
; i
++) {
746 flash_header_v3_t
*container
= &imx_header
->fhdr
[i
];
747 uint32_t container_start_offset
= ptr
- flat
;
749 /* Append container header */
750 append(ptr
, container
, HEADER_IMG_ARRAY_OFFSET
);
752 /* Adjust images offset to start from container headers start */
753 for (j
= 0; j
< container
->num_images
; j
++) {
754 container
->img
[j
].offset
-=
755 container_start_offset
+ file_offset
;
757 /* Append each image array entry */
758 for (j
= 0; j
< container
->num_images
; j
++)
759 append(ptr
, &container
->img
[j
], sizeof(boot_img_t
));
761 append(ptr
, &container
->sig_blk_hdr
, sizeof(sig_blk_hdr_t
));
763 /* Padding for container (if necessary) */
764 ptr
+= ALIGN(container
->length
, container
->padding
) -
771 static int build_container(soc_type_t soc
, uint32_t sector_size
,
772 bool emmc_fastboot
, image_t
*image_stack
,
773 bool dcd_skip
, uint8_t fuse_version
,
774 uint16_t sw_version
, int ofd
)
776 static imx_header_v3_t imx_header
;
777 image_t
*img_sp
= image_stack
;
781 char *tmp_filename
= NULL
;
783 uint32_t file_padding
= 0;
787 int cont_img_count
= 0; /* indexes to arrange the container */
789 memset((char *)&imx_header
, 0, sizeof(imx_header_v3_t
));
792 fprintf(stderr
, "Empty image stack ");
797 fprintf(stdout
, "Platform:\ti.MX8QXP B0\n");
799 fprintf(stdout
, "Platform:\ti.MX8QM B0\n");
801 set_imx_hdr_v3(&imx_header
, 0);
802 set_imx_hdr_v3(&imx_header
, 1);
804 file_off
= get_container_image_start_pos(image_stack
, sector_size
);
805 fprintf(stdout
, "container image offset (aligned):%x\n", file_off
);
807 /* step through image stack and generate the header */
808 img_sp
= image_stack
;
810 /* stop once we reach null terminator */
811 while (img_sp
->option
!= NO_IMG
) {
812 switch (img_sp
->option
) {
820 fprintf(stderr
, "No container found\n");
823 check_file(&sbuf
, img_sp
->filename
);
824 tmp_filename
= img_sp
->filename
;
825 set_image_array_entry(&imx_header
.fhdr
[container
],
826 soc
, img_sp
, file_off
,
827 ALIGN(sbuf
.st_size
, sector_size
),
828 tmp_filename
, dcd_skip
);
829 img_sp
->src
= file_off
;
831 file_off
+= ALIGN(sbuf
.st_size
, sector_size
);
837 fprintf(stderr
, "No container found\n");
840 check_file(&sbuf
, img_sp
->filename
);
841 tmp_filename
= img_sp
->filename
;
842 set_image_array_entry(&imx_header
.fhdr
[container
],
847 tmp_filename
, dcd_skip
);
848 img_sp
->src
= file_off
;
850 file_off
+= sbuf
.st_size
;
856 set_container(&imx_header
.fhdr
[container
], sw_version
,
858 CONTAINER_FLAGS_DEFAULT
,
860 /* reset img count when moving to new container */
867 * nothing to do here, the container is appended
873 * override the flags for scfw in current container
874 * mask off bottom 16 bits.
876 scfw_flags
= img_sp
->entry
& 0xFFFF0000;
879 if (file_off
> img_sp
->dst
) {
880 fprintf(stderr
, "FILEOFF address less than current file offset!!!\n");
883 if (img_sp
->dst
!= ALIGN(img_sp
->dst
, sector_size
)) {
884 fprintf(stderr
, "FILEOFF address is not aligned to sector size!!!\n");
887 file_off
= img_sp
->dst
;
891 * keep custom partition until next executable image
892 * use a global var for default behaviour
894 custom_partition
= img_sp
->entry
;
897 fprintf(stderr
, "unrecognized option in input stack (%d)\n", img_sp
->option
);
900 img_sp
++; /* advance index */
903 /* Append container (if specified) */
904 img_sp
= image_stack
;
906 if (img_sp
->option
== APPEND
) {
907 copy_file(ofd
, img_sp
->filename
, 0, 0);
908 file_padding
+= FIRST_CONTAINER_HEADER_LENGTH
;
911 } while (img_sp
->option
!= NO_IMG
);
913 /* Add padding or skip appended container */
914 ret
= lseek(ofd
, file_padding
, SEEK_SET
);
916 fprintf(stderr
, "%s: lseek error %s\n",
917 __func__
, strerror(errno
));
921 if (container
>= 0) {
922 /* Note: Image offset are not contained in the image */
923 tmp
= flatten_container_header(&imx_header
, container
+ 1,
924 &size
, file_padding
);
925 /* Write image header */
926 if (write(ofd
, tmp
, size
) != size
) {
927 fprintf(stderr
, "error writing image hdr\n");
931 /* Clean-up memory used by the headers */
936 * step through the image stack again this time copying
937 * images to final bin, stop once we reach null terminator.
939 img_sp
= image_stack
;
940 while (img_sp
->option
!= NO_IMG
) {
941 if (img_sp
->option
== M40
|| img_sp
->option
== M41
||
942 img_sp
->option
== AP
|| img_sp
->option
== DATA
||
943 img_sp
->option
== SCD
|| img_sp
->option
== SCFW
||
944 img_sp
->option
== SECO
|| img_sp
->option
== MSG_BLOCK
) {
945 copy_file_aligned(ofd
, img_sp
->filename
, img_sp
->src
,
954 int imx8image_copy_image(int outfd
, struct image_tool_params
*mparams
)
956 image_t
*img_sp
= param_stack
;
959 * SECO FW is a container image, this is to calculate the
960 * 2nd container offset.
962 fprintf(stdout
, "parsing %s\n", mparams
->imagename
);
963 parse_cfg_file(img_sp
, mparams
->imagename
);
965 if (sector_size
== 0) {
966 fprintf(stderr
, "Wrong sector size\n");
970 fprintf(stdout
, "CONTAINER Sector size:\t%08x\n", sector_size
);
971 fprintf(stdout
, "CONTAINER FUSE VERSION:\t0x%02x\n", fuse_version
);
972 fprintf(stdout
, "CONTAINER SW VERSION:\t0x%04x\n", sw_version
);
974 build_container(soc
, sector_size
, emmc_fastboot
,
975 img_sp
, false, fuse_version
, sw_version
, outfd
);
981 * imx8image parameters
985 "NXP i.MX8 Boot Image support",
988 imx8image_check_params
,
990 imx8image_print_header
,
991 imx8image_set_header
,
993 imx8image_check_image_types
,