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,