2 * Copyright (C) 2018 Alexander Graf <agraf@suse.de>
4 * SPDX-License-Identifier: GPL-2.0+
9 #include "zynqmpimage.h"
28 BIF_FLAG_HEADERSIGNATURE
,
33 BIF_FLAG_SPKSIGNATURE
,
36 BIF_FLAG_KEYSRC_ENCRYPTION
,
44 BIF_FLAG_PART_OWNER_UBOOT
,
55 char *(*parse
)(char *line
, struct bif_entry
*bf
);
58 struct bif_file_type
{
61 int (*add
)(struct bif_entry
*bf
);
67 struct image_header_table
*imgheader
;
68 struct zynqmp_header
*header
;
69 struct partition_header
*last_part
;
72 struct bif_output bif_output
;
74 static uint32_t zynqmp_csum(void *start
, void *end
)
76 uint32_t checksum
= 0;
77 uint32_t *ptr32
= start
;
79 while (ptr32
!= end
) {
80 checksum
+= le32_to_cpu(*ptr32
);
87 static int zynqmpbif_check_params(struct image_tool_params
*params
)
92 if (params
->addr
!= 0x0) {
93 fprintf(stderr
, "Error: Load Address can not be specified.\n");
98 fprintf(stderr
, "Error: Entry Point can not be specified.\n");
102 return !(params
->lflag
|| params
->dflag
);
105 static int zynqmpbif_check_image_types(uint8_t type
)
107 return (type
== IH_TYPE_ZYNQMPBIF
) ? EXIT_SUCCESS
: EXIT_FAILURE
;
110 static char *parse_dest_cpu(char *line
, struct bif_entry
*bf
)
114 for (i
= 0; i
< ARRAY_SIZE(dest_cpus
); i
++) {
115 if (!strncmp(line
, dest_cpus
[i
], strlen(dest_cpus
[i
]))) {
116 bf
->dest_cpu
= i
<< PART_ATTR_DEST_CPU_SHIFT
;
117 return line
+ strlen(dest_cpus
[i
]);
120 /* a5x can also be written as a53 */
121 if (!strncmp(dest_cpus
[i
], "a5x", 3)) {
122 char a53
[] = "a53-X";
124 a53
[4] = dest_cpus
[i
][4];
125 if (!strncmp(line
, a53
, strlen(a53
))) {
126 bf
->dest_cpu
= i
<< PART_ATTR_DEST_CPU_SHIFT
;
127 return line
+ strlen(a53
);
135 static char *parse_el(char *line
, struct bif_entry
*bf
)
137 const char *dest_els
[] = { "none", "el-0", "el-1", "el-2", "el-3" };
140 for (i
= 0; i
< ARRAY_SIZE(dest_els
); i
++) {
141 if (!strncmp(line
, dest_els
[i
], strlen(dest_els
[i
]))) {
143 return line
+ strlen(dest_els
[i
]);
150 static char *parse_load(char *line
, struct bif_entry
*bf
)
154 bf
->load
= strtoll(line
, &endptr
, 0);
159 static char *parse_entry(char *line
, struct bif_entry
*bf
)
163 bf
->entry
= strtoll(line
, &endptr
, 0);
168 static char *parse_offset(char *line
, struct bif_entry
*bf
)
172 bf
->offset
= strtoll(line
, &endptr
, 0);
177 static char *parse_partition_owner(char *line
, struct bif_entry
*bf
)
181 if (!strncmp(line
, "fsbl", 4)) {
183 } else if (!strncmp(line
, "uboot", 5)) {
184 bf
->flags
|= 1ULL << BIF_FLAG_PART_OWNER_UBOOT
;
187 printf("ERROR: Unknown partition type '%s'\n", line
);
193 static const struct bif_flags bif_flags
[] = {
194 { "fsbl_config", BIF_FLAG_FSBL_CONFIG
},
195 { "trustzone", BIF_FLAG_TZ
},
196 { "pmufw_image", BIF_FLAG_PMUFW_IMAGE
},
197 { "bootloader", BIF_FLAG_BOOTLOADER
},
198 { "destination_cpu=", 0, parse_dest_cpu
},
199 { "exception_level=", 0, parse_el
},
200 { "load=", 0, parse_load
},
201 { "startup=", 0, parse_entry
},
202 { "offset=", 0, parse_offset
},
203 { "partition_owner=", 0, parse_partition_owner
},
206 static char *read_full_file(const char *filename
, size_t *size
)
212 fd
= open(filename
, O_RDONLY
);
216 if (fstat(fd
, &sbuf
) < 0)
220 *size
= sbuf
.st_size
;
222 buf
= malloc(sbuf
.st_size
);
227 while (len
< sbuf
.st_size
) {
228 r
= read(fd
, bufp
, sbuf
.st_size
- len
);
240 static int bif_add_blob(const void *data
, size_t len
, size_t *offset
)
243 uintptr_t header_off
;
244 uintptr_t last_part_off
;
245 uintptr_t imgheader_off
;
246 uintptr_t old_data
= (uintptr_t)bif_output
.data
;
249 header_off
= (uintptr_t)bif_output
.header
- old_data
;
250 last_part_off
= (uintptr_t)bif_output
.last_part
- old_data
;
251 imgheader_off
= (uintptr_t)bif_output
.imgheader
- old_data
;
253 if (offset
&& *offset
) {
254 /* Pad to a given offset */
255 if (bif_output
.data_len
> *offset
) {
256 printf("Can not pad to offset %zx\n", *offset
);
260 bif_output
.data_len
= *offset
;
263 new_size
= ROUND(bif_output
.data_len
+ len
, 64);
264 new_data
= realloc(bif_output
.data
, new_size
);
265 memcpy(new_data
+ bif_output
.data_len
, data
, len
);
267 *offset
= bif_output
.data_len
;
268 bif_output
.data
= new_data
;
269 bif_output
.data_len
= new_size
;
271 /* Readjust internal pointers */
272 if (bif_output
.header
)
273 bif_output
.header
= new_data
+ header_off
;
274 if (bif_output
.last_part
)
275 bif_output
.last_part
= new_data
+ last_part_off
;
276 if (bif_output
.imgheader
)
277 bif_output
.imgheader
= new_data
+ imgheader_off
;
282 static int bif_init(void)
284 struct zynqmp_header header
= { { 0 } };
287 zynqmpimage_default_header(&header
);
289 r
= bif_add_blob(&header
, sizeof(header
), NULL
);
293 bif_output
.header
= (void *)bif_output
.data
;
298 static int bif_add_pmufw(struct bif_entry
*bf
, const char *data
, size_t len
)
302 if (bif_output
.header
->image_offset
) {
303 printf("PMUFW expected before bootloader in your .bif file!\n");
307 r
= bif_add_blob(data
, len
, &bf
->offset
);
311 len
= ROUND(len
, 64);
312 bif_output
.header
->pfw_image_length
= cpu_to_le32(len
);
313 bif_output
.header
->total_pfw_image_length
= cpu_to_le32(len
);
314 bif_output
.header
->image_offset
= cpu_to_le32(bf
->offset
);
319 static int bif_add_part(struct bif_entry
*bf
, const char *data
, size_t len
)
321 size_t parthdr_offset
= 0;
322 struct partition_header parthdr
= {
323 .len_enc
= cpu_to_le32(len
/ 4),
324 .len_unenc
= cpu_to_le32(len
/ 4),
325 .len
= cpu_to_le32(len
/ 4),
326 .entry_point
= cpu_to_le64(bf
->entry
),
327 .load_address
= cpu_to_le64(bf
->load
),
332 if (bf
->flags
& (1ULL << BIF_FLAG_PMUFW_IMAGE
))
333 return bif_add_pmufw(bf
, data
, len
);
335 r
= bif_add_blob(data
, len
, &bf
->offset
);
339 parthdr
.offset
= cpu_to_le32(bf
->offset
/ 4);
341 if (bf
->flags
& (1ULL << BIF_FLAG_BOOTLOADER
)) {
342 if (bif_output
.last_part
) {
343 printf("ERROR: Bootloader expected before others\n");
347 parthdr
.offset
= cpu_to_le32(bif_output
.header
->image_offset
);
348 parthdr
.len
= cpu_to_le32((bf
->offset
+ len
-
349 bif_output
.header
->image_offset
) / 4);
350 parthdr
.len_enc
= parthdr
.len
;
351 parthdr
.len_unenc
= parthdr
.len
;
355 bf
->exp_lvl
= bf
->exp_lvl
? bf
->exp_lvl
- 1 : 3;
356 parthdr
.attributes
|= bf
->exp_lvl
<< PART_ATTR_TARGET_EL_SHIFT
;
357 parthdr
.attributes
|= bf
->dest_dev
;
358 parthdr
.attributes
|= bf
->dest_cpu
;
359 if (bf
->flags
& (1ULL << BIF_FLAG_TZ
))
360 parthdr
.attributes
|= PART_ATTR_TZ_SECURE
;
361 if (bf
->flags
& (1ULL << BIF_FLAG_PART_OWNER_UBOOT
))
362 parthdr
.attributes
|= PART_ATTR_PART_OWNER_UBOOT
;
363 switch (bf
->dest_cpu
) {
364 case PART_ATTR_DEST_CPU_NONE
:
365 case PART_ATTR_DEST_CPU_A53_0
:
366 case PART_ATTR_DEST_CPU_A53_1
:
367 case PART_ATTR_DEST_CPU_A53_2
:
368 case PART_ATTR_DEST_CPU_A53_3
:
369 if (bf
->flags
& (1ULL << BIF_FLAG_AARCH32
))
370 parthdr
.attributes
|= PART_ATTR_A53_EXEC_AARCH32
;
373 csum
= zynqmp_csum(&parthdr
, &parthdr
.checksum
);
374 parthdr
.checksum
= cpu_to_le32(csum
);
376 r
= bif_add_blob(&parthdr
, sizeof(parthdr
), &parthdr_offset
);
380 /* Add image header table if not there yet */
381 if (!bif_output
.imgheader
) {
382 size_t imghdr_off
= 0;
383 struct image_header_table imghdr
= {
384 .version
= cpu_to_le32(0x01020000),
388 r
= bif_add_blob(&imghdr
, sizeof(imghdr
), &imghdr_off
);
392 bif_output
.header
->image_header_table_offset
= imghdr_off
;
393 bif_output
.imgheader
= (void *)(bif_output
.data
+ imghdr_off
);
396 bif_output
.imgheader
->nr_parts
= cpu_to_le32(le32_to_cpu(
397 bif_output
.imgheader
->nr_parts
) + 1);
399 /* Link to this partition header */
400 if (bif_output
.last_part
) {
401 bif_output
.last_part
->next_partition_offset
=
402 cpu_to_le32(parthdr_offset
/ 4);
404 /* Recalc checksum of last_part */
405 csum
= zynqmp_csum(bif_output
.last_part
,
406 &bif_output
.last_part
->checksum
);
407 bif_output
.last_part
->checksum
= cpu_to_le32(csum
);
409 bif_output
.imgheader
->partition_header_offset
=
410 cpu_to_le32(parthdr_offset
/ 4);
412 bif_output
.last_part
= (void *)(bif_output
.data
+ parthdr_offset
);
414 if (bf
->flags
& (1ULL << BIF_FLAG_BOOTLOADER
)) {
415 bif_output
.header
->image_load
= cpu_to_le32(bf
->load
);
416 if (!bif_output
.header
->image_offset
)
417 bif_output
.header
->image_offset
=
418 cpu_to_le32(bf
->offset
);
419 bif_output
.header
->image_size
= cpu_to_le32(len
);
420 bif_output
.header
->image_stored_size
= cpu_to_le32(len
);
422 bif_output
.header
->image_attributes
&= ~HEADER_CPU_SELECT_MASK
;
423 switch (bf
->dest_cpu
) {
425 case PART_ATTR_DEST_CPU_A53_0
:
426 if (bf
->flags
& BIF_FLAG_AARCH32
)
427 bif_output
.header
->image_attributes
|=
428 HEADER_CPU_SELECT_A53_32BIT
;
430 bif_output
.header
->image_attributes
|=
431 HEADER_CPU_SELECT_A53_64BIT
;
433 case PART_ATTR_DEST_CPU_R5_0
:
434 bif_output
.header
->image_attributes
|=
435 HEADER_CPU_SELECT_R5_SINGLE
;
437 case PART_ATTR_DEST_CPU_R5_L
:
438 bif_output
.header
->image_attributes
|=
439 HEADER_CPU_SELECT_R5_DUAL
;
447 /* Add .bit bitstream */
448 static int bif_add_bit(struct bif_entry
*bf
)
450 char *bit
= read_full_file(bf
->filename
, NULL
);
452 uint8_t initial_header
[] = { 0x00, 0x09, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f,
453 0xf0, 0x0f, 0xf0, 0x00, 0x00, 0x01, 0x61 };
461 /* Skip initial header */
462 if (memcmp(bit
, initial_header
, sizeof(initial_header
)))
465 bit
+= sizeof(initial_header
);
468 len
= be16_to_cpu(*(uint16_t *)bit
);
469 bit
+= sizeof(uint16_t);
470 debug("Design: %s\n", bit
);
473 /* Device identifier */
477 len
= be16_to_cpu(*(uint16_t *)bit
);
478 bit
+= sizeof(uint16_t);
479 debug("Device: %s\n", bit
);
486 len
= be16_to_cpu(*(uint16_t *)bit
);
487 bit
+= sizeof(uint16_t);
488 debug("Date: %s\n", bit
);
495 len
= be16_to_cpu(*(uint16_t *)bit
);
496 bit
+= sizeof(uint16_t);
497 debug("Time: %s\n", bit
);
500 /* Bitstream length */
504 bitlen
= be32_to_cpu(*(uint32_t *)bit
);
505 bit
+= sizeof(uint32_t);
508 debug("Bitstream Length: 0x%x\n", bitlen
);
509 for (i
= 0; i
< bitlen
; i
+= sizeof(uint32_t)) {
510 uint32_t *bitbin32
= (uint32_t *)&bitbin
[i
];
511 *bitbin32
= __swab32(*bitbin32
);
515 bf
->dest_dev
= PART_ATTR_DEST_DEVICE_PL
;
517 bf
->load
= 0xffffffff;
520 bf
->flags
|= 1ULL << BIF_FLAG_BIT_FILE
;
521 return bif_add_part(bf
, bit
, bitlen
);
524 /* Add .bin bitstream */
525 static int bif_add_bin(struct bif_entry
*bf
)
528 char *bin
= read_full_file(bf
->filename
, &size
);
531 bf
->dest_dev
= PART_ATTR_DEST_DEVICE_PS
;
533 bf
->flags
|= 1ULL << BIF_FLAG_BIN_FILE
;
534 return bif_add_part(bf
, bin
, size
);
538 static char *elf2flat64(char *elf
, size_t *flat_size
, size_t *load_addr
)
542 size_t min_addr
= -1, max_addr
= 0;
547 shdr
= (void *)(elf
+ le64_to_cpu(ehdr
->e_shoff
));
549 /* Look for smallest / biggest address */
550 for (i
= 0; i
< le64_to_cpu(ehdr
->e_shnum
); i
++, shdr
++) {
551 if (!shdr
->sh_size
|| !shdr
->sh_addr
||
552 !(shdr
->sh_flags
& SHF_ALLOC
) ||
553 (shdr
->sh_type
== SHT_NOBITS
))
556 if (le64_to_cpu(shdr
->sh_addr
) < min_addr
)
557 min_addr
= le64_to_cpu(shdr
->sh_addr
);
558 if ((le64_to_cpu(shdr
->sh_addr
) + le64_to_cpu(shdr
->sh_size
)) >
560 max_addr
= le64_to_cpu(shdr
->sh_addr
) +
561 le64_to_cpu(shdr
->sh_size
);
564 *load_addr
= min_addr
;
565 *flat_size
= max_addr
- min_addr
;
566 flat
= calloc(1, *flat_size
);
570 shdr
= (void *)(elf
+ le64_to_cpu(ehdr
->e_shoff
));
571 for (i
= 0; i
< le64_to_cpu(ehdr
->e_shnum
); i
++, shdr
++) {
572 char *dst
= flat
+ le64_to_cpu(shdr
->sh_addr
) - min_addr
;
573 char *src
= elf
+ le64_to_cpu(shdr
->sh_offset
);
575 if (!shdr
->sh_size
|| !shdr
->sh_addr
||
576 !(shdr
->sh_flags
& SHF_ALLOC
))
579 if (shdr
->sh_type
!= SHT_NOBITS
)
580 memcpy(dst
, src
, le64_to_cpu(shdr
->sh_size
));
586 static char *elf2flat32(char *elf
, size_t *flat_size
, size_t *load_addr
)
590 size_t min_addr
= -1, max_addr
= 0;
595 shdr
= (void *)(elf
+ le32_to_cpu(ehdr
->e_shoff
));
597 /* Look for smallest / biggest address */
598 for (i
= 0; i
< le32_to_cpu(ehdr
->e_shnum
); i
++, shdr
++) {
599 if (!shdr
->sh_size
|| !shdr
->sh_addr
||
600 !(shdr
->sh_flags
& SHF_ALLOC
) ||
601 (shdr
->sh_type
== SHT_NOBITS
))
604 if (le32_to_cpu(shdr
->sh_addr
) < min_addr
)
605 min_addr
= le32_to_cpu(shdr
->sh_addr
);
606 if ((le32_to_cpu(shdr
->sh_addr
) + le32_to_cpu(shdr
->sh_size
)) >
608 max_addr
= le32_to_cpu(shdr
->sh_addr
) +
609 le32_to_cpu(shdr
->sh_size
);
612 *load_addr
= min_addr
;
613 *flat_size
= max_addr
- min_addr
;
614 flat
= calloc(1, *flat_size
);
618 shdr
= (void *)(elf
+ le32_to_cpu(ehdr
->e_shoff
));
619 for (i
= 0; i
< le32_to_cpu(ehdr
->e_shnum
); i
++, shdr
++) {
620 char *dst
= flat
+ le32_to_cpu(shdr
->sh_addr
) - min_addr
;
621 char *src
= elf
+ le32_to_cpu(shdr
->sh_offset
);
623 if (!shdr
->sh_size
|| !shdr
->sh_addr
||
624 !(shdr
->sh_flags
& SHF_ALLOC
))
627 if (shdr
->sh_type
!= SHT_NOBITS
)
628 memcpy(dst
, src
, le32_to_cpu(shdr
->sh_size
));
634 static int bif_add_elf(struct bif_entry
*bf
)
644 elf
= read_full_file(bf
->filename
, &elf_size
);
648 ehdr32
= (void *)elf
;
649 ehdr64
= (void *)elf
;
651 switch (ehdr32
->e_ident
[EI_CLASS
]) {
653 flat
= elf2flat32(elf
, &size
, &load_addr
);
654 bf
->entry
= le32_to_cpu(ehdr32
->e_entry
);
655 bf
->flags
|= 1ULL << BIF_FLAG_AARCH32
;
658 flat
= elf2flat64(elf
, &size
, &load_addr
);
659 bf
->entry
= le64_to_cpu(ehdr64
->e_entry
);
662 printf("Unknown ELF class: %d\n", ehdr32
->e_ident
[EI_CLASS
]);
669 bf
->load
= load_addr
;
671 bf
->dest_dev
= PART_ATTR_DEST_DEVICE_PS
;
673 bf
->flags
|= 1ULL << BIF_FLAG_ELF_FILE
;
674 return bif_add_part(bf
, flat
, size
);
677 static const struct bif_file_type bif_file_types
[] = {
679 .name
= "bitstream (.bit)",
680 .header
= 0x00090ff0,
686 .header
= 0x7f454c46,
690 /* Anything else is a .bin file */
697 static int bif_fsbl_config(struct bif_entry
*fsbl_config
,
698 struct bif_entry
*entries
, int nr_entries
)
707 { .name
= "a5x_x64", .dest_cpu
= PART_ATTR_DEST_CPU_A53_0
},
708 { .name
= "a53_x64", .dest_cpu
= PART_ATTR_DEST_CPU_A53_0
},
709 { .name
= "a5x_x32", .dest_cpu
= PART_ATTR_DEST_CPU_A53_0
,
710 .flags
= 1ULL << BIF_FLAG_AARCH32
},
711 { .name
= "a53_x32", .dest_cpu
= PART_ATTR_DEST_CPU_A53_0
,
712 .flags
= 1ULL << BIF_FLAG_AARCH32
},
713 { .name
= "r5_single", .dest_cpu
= PART_ATTR_DEST_CPU_R5_0
},
714 { .name
= "r5_dual", .dest_cpu
= PART_ATTR_DEST_CPU_R5_L
},
717 /* Set target CPU of bootloader entry */
718 for (i
= 0; i
< nr_entries
; i
++) {
719 struct bif_entry
*b
= &entries
[i
];
720 const char *config_attr
= fsbl_config
->filename
;
723 if (!(b
->flags
& (1ULL << BIF_FLAG_BOOTLOADER
)))
726 for (j
= 0; j
< ARRAY_SIZE(configs
); j
++) {
727 if (!strncmp(config_attr
, configs
[j
].name
,
728 strlen(configs
[j
].name
))) {
729 b
->dest_cpu
= configs
[j
].dest_cpu
;
730 b
->flags
|= configs
[j
].flags
;
736 printf("ERROR: Unsupported fsbl_config: %s\n",
743 printf("ERROR: fsbl_config w/o bootloader\n");
750 static const struct bif_flags
*find_flag(char *str
)
752 const struct bif_flags
*bf
;
755 for (i
= 0; i
< ARRAY_SIZE(bif_flags
); i
++) {
757 if (!strncmp(bf
->name
, str
, strlen(bf
->name
)))
761 printf("ERROR: Flag '%s' not found\n", str
);
766 static int bif_open_file(struct bif_entry
*entry
)
768 int fd
= open(entry
->filename
, O_RDONLY
);
771 printf("Error opening file %s\n", entry
->filename
);
776 static const struct bif_file_type
*get_file_type(struct bif_entry
*entry
)
778 int fd
= bif_open_file(entry
);
785 if (read(fd
, &header
, sizeof(header
)) != sizeof(header
)) {
786 printf("Error reading file %s", entry
->filename
);
792 for (i
= 0; i
< ARRAY_SIZE(bif_file_types
); i
++) {
793 const struct bif_file_type
*type
= &bif_file_types
[i
];
797 if (type
->header
== be32_to_cpu(header
))
804 #define NEXT_CHAR(str, chr) ({ \
805 char *_n = strchr(str, chr); \
811 static char *skip_whitespace(char *str
)
813 while (*str
== ' ' || *str
== '\t')
819 int zynqmpbif_copy_image(int outfd
, struct image_tool_params
*mparams
)
821 char *bif
, *bifp
, *bifpn
;
823 struct bif_entry entries
[32] = { { 0 } };
825 struct bif_entry
*entry
= entries
;
833 /* Read .bif input file */
834 bif
= read_full_file(mparams
->datafile
, NULL
);
838 /* Interpret .bif file */
841 /* A bif description starts with a { section */
842 bifp
= NEXT_CHAR(bifp
, '{') + 1;
844 /* Read every line */
846 bifpn
= NEXT_CHAR(bifp
, '\n');
848 if (bifpn
[-1] == '\r')
855 line
= skip_whitespace(line
);
861 const struct bif_flags
*bf
;
863 line
= skip_whitespace(line
);
864 bf
= find_flag(line
);
868 line
+= strlen(bf
->name
);
870 line
= bf
->parse(line
, entry
);
872 entry
->flags
|= 1ULL << bf
->flag
;
877 /* Go to next attribute or quit */
887 /* End of image description */
892 line
= skip_whitespace(line
);
893 entry
->filename
= line
;
902 for (i
= 0; i
< nr_entries
; i
++) {
903 debug("Entry flags=%#lx name=%s\n", entries
[i
].flags
,
904 entries
[i
].filename
);
908 * Some entries are actually configuration option for other ones,
909 * let's apply them in an intermediate step.
911 for (i
= 0; i
< nr_entries
; i
++) {
912 struct bif_entry
*entry
= &entries
[i
];
914 if (entry
->flags
& (1ULL << BIF_FLAG_FSBL_CONFIG
))
915 if (bif_fsbl_config(entry
, entries
, nr_entries
))
919 /* Make sure PMUFW comes before bootloader */
920 for (i
= 0; i
< nr_entries
; i
++) {
921 struct bif_entry
*entry
= &entries
[i
];
923 if (entry
->flags
& (1ULL << BIF_FLAG_BOOTLOADER
))
925 if (entry
->flags
& (1ULL << BIF_FLAG_PMUFW_IMAGE
)) {
927 struct bif_entry tmp
= *entry
;
929 *entry
= entries
[bldr
];
935 for (i
= 0; i
< nr_entries
; i
++) {
936 struct bif_entry
*entry
= &entries
[i
];
937 const struct bif_file_type
*type
;
940 if (entry
->flags
& (1ULL << BIF_FLAG_FSBL_CONFIG
))
943 type
= get_file_type(entry
);
947 debug("type=%s file=%s\n", type
->name
, entry
->filename
);
948 r
= type
->add(entry
);
953 /* Calculate checksums */
954 csum
= zynqmp_csum(&bif_output
.header
->width_detection
,
955 &bif_output
.header
->checksum
);
956 bif_output
.header
->checksum
= cpu_to_le32(csum
);
958 if (bif_output
.imgheader
) {
959 csum
= zynqmp_csum(bif_output
.imgheader
,
960 &bif_output
.imgheader
->checksum
);
961 bif_output
.imgheader
->checksum
= cpu_to_le32(csum
);
964 /* Write headers and components */
965 if (lseek(outfd
, 0, SEEK_SET
) != 0)
968 len
= bif_output
.data_len
;
969 bifp
= bif_output
.data
;
973 r
= write(outfd
, bifp
, len
);
983 fprintf(stderr
, "Error: Failed to create image.\n");
987 /* Needs to be stubbed out so we can print after creation */
988 static void zynqmpbif_set_header(void *ptr
, struct stat
*sbuf
, int ifd
,
989 struct image_tool_params
*params
)
993 static struct zynqmp_header zynqmpimage_header
;
997 "Xilinx ZynqMP Boot Image support (bif)",
998 sizeof(struct zynqmp_header
),
999 (void *)&zynqmpimage_header
,
1000 zynqmpbif_check_params
,
1002 zynqmpimage_print_header
,
1003 zynqmpbif_set_header
,
1005 zynqmpbif_check_image_types
,