1 // SPDX-License-Identifier: GPL-2.0+
5 * Peng Fan <peng.fan@nxp.com>
11 static int sector_size
;
12 static soc_type_t soc
;
13 static int container
= -1;
14 static int32_t core_type
= CFG_CORE_INVALID
;
15 static bool emmc_fastboot
;
16 static image_t param_stack
[IMG_STACK_SIZE
];
17 static uint8_t fuse_version
;
18 static uint16_t sw_version
;
19 static uint32_t custom_partition
;
20 static uint32_t scfw_flags
;
22 int imx8image_check_params(struct image_tool_params
*params
)
27 static void imx8image_set_header(void *ptr
, struct stat
*sbuf
, int ifd
,
28 struct image_tool_params
*params
)
32 static void imx8image_print_header(const void *ptr
)
36 static int imx8image_check_image_types(uint8_t type
)
38 return (type
== IH_TYPE_IMX8IMAGE
) ? EXIT_SUCCESS
: EXIT_FAILURE
;
41 static table_entry_t imx8image_cmds
[] = {
42 {CMD_BOOT_FROM
, "BOOT_FROM", "boot command", },
43 {CMD_FUSE_VERSION
, "FUSE_VERSION", "fuse version", },
44 {CMD_SW_VERSION
, "SW_VERSION", "sw version", },
45 {CMD_MSG_BLOCK
, "MSG_BLOCK", "msg block", },
46 {CMD_FILEOFF
, "FILEOFF", "fileoff", },
47 {CMD_FLAG
, "FLAG", "flag", },
48 {CMD_APPEND
, "APPEND", "append a container", },
49 {CMD_PARTITION
, "PARTITION", "new partition", },
50 {CMD_SOC_TYPE
, "SOC_TYPE", "soc type", },
51 {CMD_CONTAINER
, "CONTAINER", "new container", },
52 {CMD_IMAGE
, "IMAGE", "new image", },
53 {CMD_DATA
, "DATA", "new data", },
57 static table_entry_t imx8image_core_entries
[] = {
58 {CFG_SCU
, "SCU", "scu core", },
59 {CFG_M40
, "M40", "M4 core 0", },
60 {CFG_M41
, "M41", "M4 core 1", },
61 {CFG_A35
, "A35", "A35 core", },
62 {CFG_A53
, "A53", "A53 core", },
63 {CFG_A72
, "A72", "A72 core", },
67 static table_entry_t imx8image_sector_size
[] = {
68 {0x400, "sd", "sd/emmc",},
69 {0x400, "emmc_fastboot", "emmc fastboot",},
70 {0x400, "fspi", "flexspi", },
71 {0x1000, "nand_4k", "nand 4K", },
72 {0x2000, "nand_8k", "nand 8K", },
73 {0x4000, "nand_16k", "nand 16K", },
74 {-1, "", "Invalid", },
77 static void parse_cfg_cmd(image_t
*param_stack
, int32_t cmd
, char *token
,
78 char *name
, int lineno
)
82 sector_size
= get_table_entry_id(imx8image_sector_size
,
83 "imximage boot option",
85 if (!strncmp("emmc_fastboot", token
, 13))
88 case CMD_FUSE_VERSION
:
89 fuse_version
= (uint8_t)(strtoll(token
, NULL
, 0) & 0xFF);
92 sw_version
= (uint8_t)(strtoll(token
, NULL
, 0) & 0xFFFF);
95 param_stack
[p_idx
].option
= FILEOFF
;
96 param_stack
[p_idx
++].dst
= (uint32_t)strtoll(token
, NULL
, 0);
99 param_stack
[p_idx
].option
= MSG_BLOCK
;
100 param_stack
[p_idx
].filename
= token
;
103 param_stack
[p_idx
].option
= FLAG
;
104 param_stack
[p_idx
++].entry
= (uint32_t)strtoll(token
, NULL
, 0);
107 param_stack
[p_idx
].option
= APPEND
;
108 param_stack
[p_idx
++].filename
= token
;
111 param_stack
[p_idx
].option
= PARTITION
;
112 param_stack
[p_idx
++].entry
= (uint32_t)strtoll(token
, NULL
, 0);
115 if (!strncmp(token
, "IMX8QX", 6)) {
117 } else if (!strncmp(token
, "IMX8QM", 6)) {
120 fprintf(stderr
, "Unknown CMD_SOC_TYPE");
126 core_type
= get_table_entry_id(imx8image_core_entries
,
127 "imx8image core entries",
130 fprintf(stderr
, "Wrong IMAGE core_type %s\n", token
);
139 static void parse_cfg_fld(image_t
*param_stack
, int32_t *cmd
, char *token
,
140 char *name
, int lineno
, int fld
)
144 *cmd
= get_table_entry_id(imx8image_cmds
, "imx8image cmds",
147 fprintf(stderr
, "Error: %s[%d] - Invalid command (%s)\n", name
, lineno
, token
);
151 if (*cmd
== CMD_CONTAINER
) {
152 fprintf(stdout
, "New Container: \t%d\n", ++container
);
153 param_stack
[p_idx
++].option
= NEW_CONTAINER
;
157 parse_cfg_cmd(param_stack
, *cmd
, token
, name
, lineno
);
160 if (*cmd
== CMD_MSG_BLOCK
) {
161 if (!strncmp(token
, "fuse", 4)) {
162 param_stack
[p_idx
].ext
= SC_R_OTP
;
163 } else if (!strncmp(token
, "debug", 5)) {
164 param_stack
[p_idx
].ext
= SC_R_DEBUG
;
165 } else if (!strncmp(token
, "field", 5)) {
166 param_stack
[p_idx
].ext
= SC_R_ROM_0
;
168 fprintf(stderr
, "MSG type not found %s\n", token
);
175 param_stack
[p_idx
].option
= SCFW
;
176 param_stack
[p_idx
++].filename
= token
;
179 param_stack
[p_idx
].option
= M40
;
180 param_stack
[p_idx
].ext
= 0;
181 param_stack
[p_idx
].filename
= token
;
184 param_stack
[p_idx
].option
= M41
;
185 param_stack
[p_idx
].ext
= 1;
186 param_stack
[p_idx
].filename
= token
;
189 param_stack
[p_idx
].ext
= CORE_CA35
;
190 param_stack
[p_idx
].option
=
191 (*cmd
== CMD_DATA
) ? DATA
: AP
;
192 param_stack
[p_idx
].filename
= token
;
195 param_stack
[p_idx
].ext
= CORE_CA53
;
196 param_stack
[p_idx
].option
=
197 (*cmd
== CMD_DATA
) ? DATA
: AP
;
198 param_stack
[p_idx
].filename
= token
;
201 param_stack
[p_idx
].ext
= CORE_CA72
;
202 param_stack
[p_idx
].option
=
203 (*cmd
== CMD_DATA
) ? DATA
: AP
;
204 param_stack
[p_idx
].filename
= token
;
209 if (*cmd
== CMD_MSG_BLOCK
) {
210 param_stack
[p_idx
++].entry
=
211 (uint32_t)strtoll(token
, NULL
, 0);
222 param_stack
[p_idx
++].entry
=
223 (uint32_t)strtoll(token
, NULL
, 0);
231 static uint32_t parse_cfg_file(image_t
*param_stack
, char *name
)
235 char *token
, *saveptr1
, *saveptr2
;
241 fd
= fopen(name
, "r");
243 fprintf(stderr
, "Error: %s - Can't open cfg file\n", name
);
248 * Very simple parsing, line starting with # are comments
251 while ((getline(&line
, &len
, fd
)) > 0) {
254 token
= strtok_r(line
, "\r\n", &saveptr1
);
258 /* Check inside the single line */
259 for (fld
= CFG_COMMAND
, cmd
= CFG_INVALID
,
260 line
= token
; ; line
= NULL
, fld
++) {
261 token
= strtok_r(line
, " \t", &saveptr2
);
265 /* Drop all text starting with '#' as comments */
269 parse_cfg_fld(param_stack
, &cmd
, token
, name
, lineno
,
277 static void check_file(struct stat
*sbuf
, char *filename
)
279 int tmp_fd
= open(filename
, O_RDONLY
| O_BINARY
);
282 fprintf(stderr
, "%s: Can't open: %s\n",
283 filename
, strerror(errno
));
287 if (fstat(tmp_fd
, sbuf
) < 0) {
288 fprintf(stderr
, "%s: Can't stat: %s\n",
289 filename
, strerror(errno
));
296 static void copy_file_aligned(int ifd
, const char *datafile
, int offset
,
302 uint8_t zeros
[0x4000];
306 if (align
> 0x4000) {
307 fprintf(stderr
, "Wrong alignment requested %d\n", align
);
311 memset(zeros
, 0, sizeof(zeros
));
313 dfd
= open(datafile
, O_RDONLY
| O_BINARY
);
315 fprintf(stderr
, "Can't open %s: %s\n",
316 datafile
, strerror(errno
));
320 if (fstat(dfd
, &sbuf
) < 0) {
321 fprintf(stderr
, "Can't stat %s: %s\n",
322 datafile
, strerror(errno
));
326 if (sbuf
.st_size
== 0)
329 ptr
= mmap(0, sbuf
.st_size
, PROT_READ
, MAP_SHARED
, dfd
, 0);
330 if (ptr
== MAP_FAILED
) {
331 fprintf(stderr
, "Can't read %s: %s\n",
332 datafile
, strerror(errno
));
337 ret
= lseek(ifd
, offset
, SEEK_SET
);
339 fprintf(stderr
, "%s: lseek error %s\n",
340 __func__
, strerror(errno
));
344 if (write(ifd
, ptr
, size
) != size
) {
345 fprintf(stderr
, "Write error %s\n", strerror(errno
));
349 align
= ALIGN(size
, align
) - size
;
351 if (write(ifd
, (char *)&zeros
, align
) != align
) {
352 fprintf(stderr
, "Write error: %s\n", strerror(errno
));
356 munmap((void *)ptr
, sbuf
.st_size
);
361 static void copy_file (int ifd
, const char *datafile
, int pad
, int offset
)
371 memset(zeros
, 0, sizeof(zeros
));
373 dfd
= open(datafile
, O_RDONLY
| O_BINARY
);
375 fprintf(stderr
, "Can't open %s: %s\n",
376 datafile
, strerror(errno
));
380 if (fstat(dfd
, &sbuf
) < 0) {
381 fprintf(stderr
, "Can't stat %s: %s\n",
382 datafile
, strerror(errno
));
386 if (sbuf
.st_size
== 0)
389 ptr
= mmap(0, sbuf
.st_size
, PROT_READ
, MAP_SHARED
, dfd
, 0);
390 if (ptr
== MAP_FAILED
) {
391 fprintf(stderr
, "Can't read %s: %s\n",
392 datafile
, strerror(errno
));
397 ret
= lseek(ifd
, offset
, SEEK_SET
);
399 fprintf(stderr
, "%s: lseek error %s\n",
400 __func__
, strerror(errno
));
404 if (write(ifd
, ptr
, size
) != size
) {
405 fprintf(stderr
, "Write error %s\n",
412 if (pad
== 1 && tail
!= 0) {
413 if (write(ifd
, (char *)&zero
, 4 - tail
) != 4 - tail
) {
414 fprintf(stderr
, "Write error on %s\n",
418 } else if (pad
> 1) {
420 int todo
= sizeof(zeros
);
424 if (write(ifd
, (char *)&zeros
, todo
) != todo
) {
425 fprintf(stderr
, "Write error: %s\n",
433 munmap((void *)ptr
, sbuf
.st_size
);
438 uint64_t read_dcd_offset(char *filename
)
445 dfd
= open(filename
, O_RDONLY
| O_BINARY
);
447 fprintf(stderr
, "Can't open %s: %s\n", filename
, strerror(errno
));
451 if (fstat(dfd
, &sbuf
) < 0) {
452 fprintf(stderr
, "Can't stat %s: %s\n", filename
, strerror(errno
));
456 ptr
= mmap(0, sbuf
.st_size
, PROT_READ
, MAP_SHARED
, dfd
, 0);
457 if (ptr
== MAP_FAILED
) {
458 fprintf(stderr
, "Can't read %s: %s\n", filename
, strerror(errno
));
462 offset
= *(uint32_t *)(ptr
+ DCD_ENTRY_ADDR_IN_SCFW
);
464 munmap((void *)ptr
, sbuf
.st_size
);
470 static void set_image_hash(boot_img_t
*img
, char *filename
, uint32_t hash_type
)
473 char sha_command
[512];
474 char hash
[2 * HASH_MAX_LEN
+ 1];
478 sprintf(sha_command
, "sha%dsum /dev/null", hash_type
);
480 sprintf(sha_command
, "dd if=/dev/zero of=tmp_pad bs=%d count=1;\
481 dd if=\'%s\' of=tmp_pad conv=notrunc;\
482 sha%dsum tmp_pad; rm -f tmp_pad",
483 img
->size
, filename
, hash_type
);
486 case HASH_TYPE_SHA_256
:
487 img
->hab_flags
|= IMG_FLAG_HASH_SHA256
;
489 case HASH_TYPE_SHA_384
:
490 img
->hab_flags
|= IMG_FLAG_HASH_SHA384
;
492 case HASH_TYPE_SHA_512
:
493 img
->hab_flags
|= IMG_FLAG_HASH_SHA512
;
496 fprintf(stderr
, "Wrong hash type selected (%d) !!!\n\n",
501 memset(img
->hash
, 0, HASH_MAX_LEN
);
503 fp
= popen(sha_command
, "r");
505 fprintf(stderr
, "Failed to run command hash\n");
509 if (!fgets(hash
, hash_type
/ 4 + 1, fp
)) {
510 fprintf(stderr
, "Failed to hash file: %s\n", filename
);
514 for (i
= 0; i
< strlen(hash
) / 2; i
++) {
515 ret
= sscanf(hash
+ 2 * i
, "%02hhx", &img
->hash
[i
]);
517 fprintf(stderr
, "Failed sscanf hash: %d\n", ret
);
525 static void set_image_array_entry(flash_header_v3_t
*container
,
526 soc_type_t soc
, const image_t
*image_stack
,
527 uint32_t offset
, uint32_t size
,
528 char *tmp_filename
, bool dcd_skip
)
530 uint64_t entry
= image_stack
->entry
;
531 uint64_t core
= image_stack
->ext
;
534 option_type_t type
= image_stack
->option
;
535 boot_img_t
*img
= &container
->img
[container
->num_images
];
537 img
->offset
= offset
; /* Is re-adjusted later */
540 set_image_hash(img
, tmp_filename
, IMAGE_HASH_ALGO_DEFAULT
);
544 img
->hab_flags
|= IMG_TYPE_SECO
;
545 img
->hab_flags
|= CORE_SECO
<< BOOT_IMG_FLAGS_CORE_SHIFT
;
547 img
->dst
= 0x20C00000;
548 img
->entry
= 0x20000000;
551 if (soc
== QX
&& core
== CORE_CA35
) {
552 meta
= IMAGE_A35_DEFAULT_META(custom_partition
);
553 } else if (soc
== QM
&& core
== CORE_CA53
) {
554 meta
= IMAGE_A53_DEFAULT_META(custom_partition
);
555 } else if (soc
== QM
&& core
== CORE_CA72
) {
556 meta
= IMAGE_A72_DEFAULT_META(custom_partition
);
559 "Error: invalid AP core id: %" PRIu64
"\n",
563 img
->hab_flags
|= IMG_TYPE_EXEC
;
564 /* On B0, only core id = 4 is valid */
565 img
->hab_flags
|= CORE_CA53
<< BOOT_IMG_FLAGS_CORE_SHIFT
;
570 custom_partition
= 0;
576 meta
= IMAGE_M4_0_DEFAULT_META(custom_partition
);
577 } else if (core
== 1) {
579 meta
= IMAGE_M4_1_DEFAULT_META(custom_partition
);
582 "Error: invalid m4 core id: %" PRIu64
"\n",
586 img
->hab_flags
|= IMG_TYPE_EXEC
;
587 img
->hab_flags
|= core
<< BOOT_IMG_FLAGS_CORE_SHIFT
;
589 if ((entry
& 0x7) != 0) {
590 fprintf(stderr
, "\n\nWarning: M4 Destination address is not 8 byte aligned\n\n");
596 custom_partition
= 0;
599 img
->hab_flags
|= IMG_TYPE_DATA
;
600 img
->hab_flags
|= CORE_CA35
<< BOOT_IMG_FLAGS_CORE_SHIFT
;
605 img
->hab_flags
|= IMG_TYPE_DATA
;
606 img
->hab_flags
|= CORE_CA35
<< BOOT_IMG_FLAGS_CORE_SHIFT
;
607 img
->meta
= core
<< BOOT_IMG_META_MU_RID_SHIFT
;
608 tmp_name
= "MSG_BLOCK";
612 img
->hab_flags
|= scfw_flags
& 0xFFFF0000;
613 img
->hab_flags
|= IMG_TYPE_EXEC
;
614 img
->hab_flags
|= CORE_SC
<< BOOT_IMG_FLAGS_CORE_SHIFT
;
616 img
->dst
= 0x1FFE0000;
617 img
->entry
= 0x1FFE0000;
619 /* Lets add the DCD now */
621 container
->num_images
++;
622 img
= &container
->img
[container
->num_images
];
623 img
->hab_flags
|= IMG_TYPE_DCD_DDR
;
624 img
->hab_flags
|= CORE_SC
<< BOOT_IMG_FLAGS_CORE_SHIFT
;
625 set_image_hash(img
, "/dev/null",
626 IMAGE_HASH_ALGO_DEFAULT
);
627 img
->offset
= offset
+ img
->size
;
628 img
->entry
= read_dcd_offset(tmp_filename
);
629 img
->dst
= img
->entry
- 1;
633 fprintf(stderr
, "unrecognized image type (%d)\n", type
);
637 fprintf(stdout
, "%s file_offset = 0x%x size = 0x%x\n", tmp_name
, offset
, size
);
639 container
->num_images
++;
642 void set_container(flash_header_v3_t
*container
, uint16_t sw_version
,
643 uint32_t alignment
, uint32_t flags
, uint16_t fuse_version
)
645 container
->sig_blk_hdr
.tag
= 0x90;
646 container
->sig_blk_hdr
.length
= sizeof(sig_blk_hdr_t
);
647 container
->sw_version
= sw_version
;
648 container
->padding
= alignment
;
649 container
->fuse_version
= fuse_version
;
650 container
->flags
= flags
;
651 fprintf(stdout
, "container flags: 0x%x\n", container
->flags
);
654 static int get_container_image_start_pos(image_t
*image_stack
, uint32_t align
)
656 image_t
*img_sp
= image_stack
;
657 /*8K total container header*/
658 int file_off
= CONTAINER_IMAGE_ARRAY_START_OFFSET
;
660 flash_header_v3_t header
;
663 while (img_sp
->option
!= NO_IMG
) {
664 if (img_sp
->option
== APPEND
) {
665 fd
= fopen(img_sp
->filename
, "r");
667 fprintf(stderr
, "Fail open first container file %s\n", img_sp
->filename
);
671 ret
= fread(&header
, sizeof(header
), 1, fd
);
673 printf("Failure Read header %d\n", ret
);
679 if (header
.tag
!= IVT_HEADER_TAG_B0
) {
680 fprintf(stderr
, "header tag mismatched \n");
684 header
.img
[header
.num_images
- 1].size
;
685 file_off
= ALIGN(file_off
, align
);
695 static void set_imx_hdr_v3(imx_header_v3_t
*imxhdr
, uint32_t cont_id
)
697 flash_header_v3_t
*fhdr_v3
= &imxhdr
->fhdr
[cont_id
];
699 /* Set magic number, Only >= B0 supported */
700 fhdr_v3
->tag
= IVT_HEADER_TAG_B0
;
701 fhdr_v3
->version
= IVT_VERSION_B0
;
704 static uint8_t *flatten_container_header(imx_header_v3_t
*imx_header
,
705 uint8_t containers_count
,
707 uint32_t file_offset
)
709 uint8_t *flat
= NULL
;
714 /* Compute size of all container headers */
715 for (i
= 0; i
< containers_count
; i
++) {
716 flash_header_v3_t
*container
= &imx_header
->fhdr
[i
];
718 container
->sig_blk_offset
= HEADER_IMG_ARRAY_OFFSET
+
719 container
->num_images
* IMG_ARRAY_ENTRY_SIZE
;
721 container
->length
= HEADER_IMG_ARRAY_OFFSET
+
722 (IMG_ARRAY_ENTRY_SIZE
* container
->num_images
) +
723 sizeof(sig_blk_hdr_t
);
725 /* Print info needed by CST to sign the container header */
726 fprintf(stdout
, "CST: CONTAINER %d offset: 0x%x\n",
727 i
, file_offset
+ size
);
728 fprintf(stdout
, "CST: CONTAINER %d: Signature Block: offset is at 0x%x\n", i
,
729 file_offset
+ size
+ container
->length
-
730 SIGNATURE_BLOCK_HEADER_LENGTH
);
732 size
+= ALIGN(container
->length
, container
->padding
);
735 flat
= calloc(size
, sizeof(uint8_t));
737 fprintf(stderr
, "Failed to allocate memory (%d)\n", size
);
744 for (i
= 0; i
< containers_count
; i
++) {
745 flash_header_v3_t
*container
= &imx_header
->fhdr
[i
];
746 uint32_t container_start_offset
= ptr
- flat
;
748 /* Append container header */
749 append(ptr
, container
, HEADER_IMG_ARRAY_OFFSET
);
751 /* Adjust images offset to start from container headers start */
752 for (j
= 0; j
< container
->num_images
; j
++) {
753 container
->img
[j
].offset
-=
754 container_start_offset
+ file_offset
;
756 /* Append each image array entry */
757 for (j
= 0; j
< container
->num_images
; j
++)
758 append(ptr
, &container
->img
[j
], sizeof(boot_img_t
));
760 append(ptr
, &container
->sig_blk_hdr
, sizeof(sig_blk_hdr_t
));
762 /* Padding for container (if necessary) */
763 ptr
+= ALIGN(container
->length
, container
->padding
) -
770 static int build_container(soc_type_t soc
, uint32_t sector_size
,
771 bool emmc_fastboot
, image_t
*image_stack
,
772 bool dcd_skip
, uint8_t fuse_version
,
773 uint16_t sw_version
, int ofd
)
775 static imx_header_v3_t imx_header
;
776 image_t
*img_sp
= image_stack
;
780 char *tmp_filename
= NULL
;
782 uint32_t file_padding
= 0;
786 int cont_img_count
= 0; /* indexes to arrange the container */
788 memset((char *)&imx_header
, 0, sizeof(imx_header_v3_t
));
791 fprintf(stderr
, "Empty image stack ");
796 fprintf(stdout
, "Platform:\ti.MX8QXP B0\n");
798 fprintf(stdout
, "Platform:\ti.MX8QM B0\n");
800 set_imx_hdr_v3(&imx_header
, 0);
801 set_imx_hdr_v3(&imx_header
, 1);
803 file_off
= get_container_image_start_pos(image_stack
, sector_size
);
804 fprintf(stdout
, "container image offset (aligned):%x\n", file_off
);
806 /* step through image stack and generate the header */
807 img_sp
= image_stack
;
809 /* stop once we reach null terminator */
810 while (img_sp
->option
!= NO_IMG
) {
811 switch (img_sp
->option
) {
819 fprintf(stderr
, "No container found\n");
822 check_file(&sbuf
, img_sp
->filename
);
823 tmp_filename
= img_sp
->filename
;
824 set_image_array_entry(&imx_header
.fhdr
[container
],
825 soc
, img_sp
, file_off
,
826 ALIGN(sbuf
.st_size
, sector_size
),
827 tmp_filename
, dcd_skip
);
828 img_sp
->src
= file_off
;
830 file_off
+= ALIGN(sbuf
.st_size
, sector_size
);
836 fprintf(stderr
, "No container found\n");
839 check_file(&sbuf
, img_sp
->filename
);
840 tmp_filename
= img_sp
->filename
;
841 set_image_array_entry(&imx_header
.fhdr
[container
],
846 tmp_filename
, dcd_skip
);
847 img_sp
->src
= file_off
;
849 file_off
+= sbuf
.st_size
;
855 set_container(&imx_header
.fhdr
[container
], sw_version
,
857 CONTAINER_FLAGS_DEFAULT
,
859 /* reset img count when moving to new container */
866 * nothing to do here, the container is appended
872 * override the flags for scfw in current container
873 * mask off bottom 16 bits.
875 scfw_flags
= img_sp
->entry
& 0xFFFF0000;
878 if (file_off
> img_sp
->dst
) {
879 fprintf(stderr
, "FILEOFF address less than current file offset!!!\n");
882 if (img_sp
->dst
!= ALIGN(img_sp
->dst
, sector_size
)) {
883 fprintf(stderr
, "FILEOFF address is not aligned to sector size!!!\n");
886 file_off
= img_sp
->dst
;
890 * keep custom partition until next executable image
891 * use a global var for default behaviour
893 custom_partition
= img_sp
->entry
;
896 fprintf(stderr
, "unrecognized option in input stack (%d)\n", img_sp
->option
);
899 img_sp
++; /* advance index */
902 /* Append container (if specified) */
903 img_sp
= image_stack
;
905 if (img_sp
->option
== APPEND
) {
906 copy_file(ofd
, img_sp
->filename
, 0, 0);
907 file_padding
+= FIRST_CONTAINER_HEADER_LENGTH
;
910 } while (img_sp
->option
!= NO_IMG
);
912 /* Add padding or skip appended container */
913 ret
= lseek(ofd
, file_padding
, SEEK_SET
);
915 fprintf(stderr
, "%s: lseek error %s\n",
916 __func__
, strerror(errno
));
920 if (container
>= 0) {
921 /* Note: Image offset are not contained in the image */
922 tmp
= flatten_container_header(&imx_header
, container
+ 1,
923 &size
, file_padding
);
924 /* Write image header */
925 if (write(ofd
, tmp
, size
) != size
) {
926 fprintf(stderr
, "error writing image hdr\n");
930 /* Clean-up memory used by the headers */
935 * step through the image stack again this time copying
936 * images to final bin, stop once we reach null terminator.
938 img_sp
= image_stack
;
939 while (img_sp
->option
!= NO_IMG
) {
940 if (img_sp
->option
== M40
|| img_sp
->option
== M41
||
941 img_sp
->option
== AP
|| img_sp
->option
== DATA
||
942 img_sp
->option
== SCD
|| img_sp
->option
== SCFW
||
943 img_sp
->option
== SECO
|| img_sp
->option
== MSG_BLOCK
) {
944 copy_file_aligned(ofd
, img_sp
->filename
, img_sp
->src
,
953 int imx8image_copy_image(int outfd
, struct image_tool_params
*mparams
)
955 image_t
*img_sp
= param_stack
;
958 * SECO FW is a container image, this is to calculate the
959 * 2nd container offset.
961 fprintf(stdout
, "parsing %s\n", mparams
->imagename
);
962 parse_cfg_file(img_sp
, mparams
->imagename
);
964 if (sector_size
== 0) {
965 fprintf(stderr
, "Wrong sector size\n");
969 fprintf(stdout
, "CONTAINER Sector size:\t%08x\n", sector_size
);
970 fprintf(stdout
, "CONTAINER FUSE VERSION:\t0x%02x\n", fuse_version
);
971 fprintf(stdout
, "CONTAINER SW VERSION:\t0x%04x\n", sw_version
);
973 build_container(soc
, sector_size
, emmc_fastboot
,
974 img_sp
, false, fuse_version
, sw_version
, outfd
);
980 * imx8image parameters
984 "NXP i.MX8 Boot Image support",
987 imx8image_check_params
,
989 imx8image_print_header
,
990 imx8image_set_header
,
992 imx8image_check_image_types
,