Home | History | Annotate | Download | only in tools
      1 /*
      2  * Copyright (C) 2018 Alexander Graf <agraf (at) suse.de>
      3  *
      4  * SPDX-License-Identifier:	GPL-2.0+
      5  */
      6 
      7 #include "imagetool.h"
      8 #include "mkimage.h"
      9 #include "zynqmpimage.h"
     10 #include <elf.h>
     11 #include <image.h>
     12 
     13 struct bif_entry {
     14 	const char *filename;
     15 	uint64_t flags;
     16 	uint64_t dest_cpu;
     17 	uint64_t exp_lvl;
     18 	uint64_t dest_dev;
     19 	uint64_t load;
     20 	uint64_t entry;
     21 	size_t offset;
     22 };
     23 
     24 enum bif_flag {
     25 	BIF_FLAG_AESKEYFILE,
     26 	BIF_FLAG_INIT,
     27 	BIF_FLAG_UDF_BH,
     28 	BIF_FLAG_HEADERSIGNATURE,
     29 	BIF_FLAG_PPKFILE,
     30 	BIF_FLAG_PSKFILE,
     31 	BIF_FLAG_SPKFILE,
     32 	BIF_FLAG_SSKFILE,
     33 	BIF_FLAG_SPKSIGNATURE,
     34 	BIF_FLAG_FSBL_CONFIG,
     35 	BIF_FLAG_AUTH_PARAMS,
     36 	BIF_FLAG_KEYSRC_ENCRYPTION,
     37 	BIF_FLAG_PMUFW_IMAGE,
     38 	BIF_FLAG_BOOTLOADER,
     39 	BIF_FLAG_TZ,
     40 	BIF_FLAG_BH_KEY_IV,
     41 	BIF_FLAG_BH_KEYFILE,
     42 	BIF_FLAG_PUF_FILE,
     43 	BIF_FLAG_AARCH32,
     44 	BIF_FLAG_PART_OWNER_UBOOT,
     45 
     46 	/* Internal flags */
     47 	BIF_FLAG_BIT_FILE,
     48 	BIF_FLAG_ELF_FILE,
     49 	BIF_FLAG_BIN_FILE,
     50 };
     51 
     52 struct bif_flags {
     53 	const char name[32];
     54 	uint64_t flag;
     55 	char *(*parse)(char *line, struct bif_entry *bf);
     56 };
     57 
     58 struct bif_file_type {
     59 	const char name[32];
     60 	uint32_t header;
     61 	int (*add)(struct bif_entry *bf);
     62 };
     63 
     64 struct bif_output {
     65 	size_t data_len;
     66 	char *data;
     67 	struct image_header_table *imgheader;
     68 	struct zynqmp_header *header;
     69 	struct partition_header *last_part;
     70 };
     71 
     72 struct bif_output bif_output;
     73 
     74 static uint32_t zynqmp_csum(void *start, void *end)
     75 {
     76 	uint32_t checksum = 0;
     77 	uint32_t *ptr32 = start;
     78 
     79 	while (ptr32 != end) {
     80 		checksum += le32_to_cpu(*ptr32);
     81 		ptr32++;
     82 	}
     83 
     84 	return ~checksum;
     85 }
     86 
     87 static int zynqmpbif_check_params(struct image_tool_params *params)
     88 {
     89 	if (!params)
     90 		return 0;
     91 
     92 	if (params->addr != 0x0) {
     93 		fprintf(stderr, "Error: Load Address can not be specified.\n");
     94 		return -1;
     95 	}
     96 
     97 	if (params->eflag) {
     98 		fprintf(stderr, "Error: Entry Point can not be specified.\n");
     99 		return -1;
    100 	}
    101 
    102 	return !(params->lflag || params->dflag);
    103 }
    104 
    105 static int zynqmpbif_check_image_types(uint8_t type)
    106 {
    107 	return (type == IH_TYPE_ZYNQMPBIF) ? EXIT_SUCCESS : EXIT_FAILURE;
    108 }
    109 
    110 static char *parse_dest_cpu(char *line, struct bif_entry *bf)
    111 {
    112 	uint64_t i;
    113 
    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]);
    118 		}
    119 
    120 		/* a5x can also be written as a53 */
    121 		if (!strncmp(dest_cpus[i], "a5x", 3)) {
    122 			char a53[] = "a53-X";
    123 
    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);
    128 			}
    129 		}
    130 	}
    131 
    132 	return line;
    133 }
    134 
    135 static char *parse_el(char *line, struct bif_entry *bf)
    136 {
    137 	const char *dest_els[] = { "none", "el-0", "el-1", "el-2", "el-3" };
    138 	int i;
    139 
    140 	for (i = 0; i < ARRAY_SIZE(dest_els); i++) {
    141 		if (!strncmp(line, dest_els[i], strlen(dest_els[i]))) {
    142 			bf->exp_lvl = i;
    143 			return line + strlen(dest_els[i]);
    144 		}
    145 	}
    146 
    147 	return line;
    148 }
    149 
    150 static char *parse_load(char *line, struct bif_entry *bf)
    151 {
    152 	char *endptr;
    153 
    154 	bf->load = strtoll(line, &endptr, 0);
    155 
    156 	return endptr;
    157 }
    158 
    159 static char *parse_entry(char *line, struct bif_entry *bf)
    160 {
    161 	char *endptr;
    162 
    163 	bf->entry = strtoll(line, &endptr, 0);
    164 
    165 	return endptr;
    166 }
    167 
    168 static char *parse_offset(char *line, struct bif_entry *bf)
    169 {
    170 	char *endptr;
    171 
    172 	bf->offset = strtoll(line, &endptr, 0);
    173 
    174 	return endptr;
    175 }
    176 
    177 static char *parse_partition_owner(char *line, struct bif_entry *bf)
    178 {
    179 	char *endptr = NULL;
    180 
    181 	if (!strncmp(line, "fsbl", 4)) {
    182 		endptr = line + 4;
    183 	} else if (!strncmp(line, "uboot", 5)) {
    184 		bf->flags |= 1ULL << BIF_FLAG_PART_OWNER_UBOOT;
    185 		endptr = line + 5;
    186 	} else {
    187 		printf("ERROR: Unknown partition type '%s'\n", line);
    188 	}
    189 
    190 	return endptr;
    191 }
    192 
    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 },
    204 };
    205 
    206 static char *read_full_file(const char *filename, size_t *size)
    207 {
    208 	char *buf, *bufp;
    209 	struct stat sbuf;
    210 	int len = 0, r, fd;
    211 
    212 	fd = open(filename, O_RDONLY);
    213 	if (fd < 0)
    214 		return NULL;
    215 
    216 	if (fstat(fd, &sbuf) < 0)
    217 		return NULL;
    218 
    219 	if (size)
    220 		*size = sbuf.st_size;
    221 
    222 	buf = malloc(sbuf.st_size);
    223 	if (!buf)
    224 		return NULL;
    225 
    226 	bufp = buf;
    227 	while (len < sbuf.st_size) {
    228 		r = read(fd, bufp, sbuf.st_size - len);
    229 		if (r < 0)
    230 			return NULL;
    231 		len += r;
    232 		bufp += r;
    233 	}
    234 
    235 	close(fd);
    236 
    237 	return buf;
    238 }
    239 
    240 static int bif_add_blob(const void *data, size_t len, size_t *offset)
    241 {
    242 	size_t new_size;
    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;
    247 	void *new_data;
    248 
    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;
    252 
    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);
    257 			return -1;
    258 		}
    259 
    260 		bif_output.data_len = *offset;
    261 	}
    262 
    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);
    266 	if (offset)
    267 		*offset = bif_output.data_len;
    268 	bif_output.data = new_data;
    269 	bif_output.data_len = new_size;
    270 
    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;
    278 
    279 	return 0;
    280 }
    281 
    282 static int bif_init(void)
    283 {
    284 	struct zynqmp_header header = { { 0 } };
    285 	int r;
    286 
    287 	zynqmpimage_default_header(&header);
    288 
    289 	r = bif_add_blob(&header, sizeof(header), NULL);
    290 	if (r)
    291 		return r;
    292 
    293 	bif_output.header = (void *)bif_output.data;
    294 
    295 	return 0;
    296 }
    297 
    298 static int bif_add_pmufw(struct bif_entry *bf, const char *data, size_t len)
    299 {
    300 	int r;
    301 
    302 	if (bif_output.header->image_offset) {
    303 		printf("PMUFW expected before bootloader in your .bif file!\n");
    304 		return -1;
    305 	}
    306 
    307 	r = bif_add_blob(data, len, &bf->offset);
    308 	if (r)
    309 		return r;
    310 
    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);
    315 
    316 	return 0;
    317 }
    318 
    319 static int bif_add_part(struct bif_entry *bf, const char *data, size_t len)
    320 {
    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),
    328 	};
    329 	int r;
    330 	uint32_t csum;
    331 
    332 	if (bf->flags & (1ULL << BIF_FLAG_PMUFW_IMAGE))
    333 		return bif_add_pmufw(bf, data, len);
    334 
    335 	r = bif_add_blob(data, len, &bf->offset);
    336 	if (r)
    337 		return r;
    338 
    339 	parthdr.offset = cpu_to_le32(bf->offset / 4);
    340 
    341 	if (bf->flags & (1ULL << BIF_FLAG_BOOTLOADER)) {
    342 		if (bif_output.last_part) {
    343 			printf("ERROR: Bootloader expected before others\n");
    344 			return -1;
    345 		}
    346 
    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;
    352 	}
    353 
    354 	/* Normalize EL */
    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;
    371 	}
    372 
    373 	csum = zynqmp_csum(&parthdr, &parthdr.checksum);
    374 	parthdr.checksum = cpu_to_le32(csum);
    375 
    376 	r = bif_add_blob(&parthdr, sizeof(parthdr), &parthdr_offset);
    377 	if (r)
    378 		return r;
    379 
    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),
    385 			.nr_parts = 0,
    386 		};
    387 
    388 		r = bif_add_blob(&imghdr, sizeof(imghdr), &imghdr_off);
    389 		if (r)
    390 			return r;
    391 
    392 		bif_output.header->image_header_table_offset = imghdr_off;
    393 		bif_output.imgheader = (void *)(bif_output.data + imghdr_off);
    394 	}
    395 
    396 	bif_output.imgheader->nr_parts = cpu_to_le32(le32_to_cpu(
    397 		bif_output.imgheader->nr_parts) + 1);
    398 
    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);
    403 
    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);
    408 	} else {
    409 		bif_output.imgheader->partition_header_offset =
    410 			cpu_to_le32(parthdr_offset / 4);
    411 	}
    412 	bif_output.last_part = (void *)(bif_output.data + parthdr_offset);
    413 
    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);
    421 
    422 		bif_output.header->image_attributes &= ~HEADER_CPU_SELECT_MASK;
    423 		switch (bf->dest_cpu) {
    424 		default:
    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;
    429 			else
    430 				bif_output.header->image_attributes |=
    431 					HEADER_CPU_SELECT_A53_64BIT;
    432 			break;
    433 		case PART_ATTR_DEST_CPU_R5_0:
    434 			bif_output.header->image_attributes |=
    435 				HEADER_CPU_SELECT_R5_SINGLE;
    436 			break;
    437 		case PART_ATTR_DEST_CPU_R5_L:
    438 			bif_output.header->image_attributes |=
    439 				HEADER_CPU_SELECT_R5_DUAL;
    440 			break;
    441 		}
    442 	}
    443 
    444 	return 0;
    445 }
    446 
    447 /* Add .bit bitstream */
    448 static int bif_add_bit(struct bif_entry *bf)
    449 {
    450 	char *bit = read_full_file(bf->filename, NULL);
    451 	char *bitbin;
    452 	uint8_t initial_header[] = { 0x00, 0x09, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f,
    453 				     0xf0, 0x0f, 0xf0, 0x00, 0x00, 0x01, 0x61 };
    454 	uint16_t len;
    455 	uint32_t bitlen;
    456 	int i;
    457 
    458 	if (!bit)
    459 		return -1;
    460 
    461 	/* Skip initial header */
    462 	if (memcmp(bit, initial_header, sizeof(initial_header)))
    463 		return -1;
    464 
    465 	bit += sizeof(initial_header);
    466 
    467 	/* Design name */
    468 	len = be16_to_cpu(*(uint16_t *)bit);
    469 	bit += sizeof(uint16_t);
    470 	debug("Design: %s\n", bit);
    471 	bit += len;
    472 
    473 	/* Device identifier */
    474 	if (*bit != 'b')
    475 		return -1;
    476 	bit++;
    477 	len = be16_to_cpu(*(uint16_t *)bit);
    478 	bit += sizeof(uint16_t);
    479 	debug("Device: %s\n", bit);
    480 	bit += len;
    481 
    482 	/* Date */
    483 	if (*bit != 'c')
    484 		return -1;
    485 	bit++;
    486 	len = be16_to_cpu(*(uint16_t *)bit);
    487 	bit += sizeof(uint16_t);
    488 	debug("Date: %s\n", bit);
    489 	bit += len;
    490 
    491 	/* Time */
    492 	if (*bit != 'd')
    493 		return -1;
    494 	bit++;
    495 	len = be16_to_cpu(*(uint16_t *)bit);
    496 	bit += sizeof(uint16_t);
    497 	debug("Time: %s\n", bit);
    498 	bit += len;
    499 
    500 	/* Bitstream length */
    501 	if (*bit != 'e')
    502 		return -1;
    503 	bit++;
    504 	bitlen = be32_to_cpu(*(uint32_t *)bit);
    505 	bit += sizeof(uint32_t);
    506 	bitbin = bit;
    507 
    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);
    512 	}
    513 
    514 	if (!bf->dest_dev)
    515 		bf->dest_dev = PART_ATTR_DEST_DEVICE_PL;
    516 
    517 	bf->load = 0xffffffff;
    518 	bf->entry = 0;
    519 
    520 	bf->flags |= 1ULL << BIF_FLAG_BIT_FILE;
    521 	return bif_add_part(bf, bit, bitlen);
    522 }
    523 
    524 /* Add .bin bitstream */
    525 static int bif_add_bin(struct bif_entry *bf)
    526 {
    527 	size_t size;
    528 	char *bin = read_full_file(bf->filename, &size);
    529 
    530 	if (!bf->dest_dev)
    531 		bf->dest_dev = PART_ATTR_DEST_DEVICE_PS;
    532 
    533 	bf->flags |= 1ULL << BIF_FLAG_BIN_FILE;
    534 	return bif_add_part(bf, bin, size);
    535 }
    536 
    537 /* Add elf file */
    538 static char *elf2flat64(char *elf, size_t *flat_size, size_t *load_addr)
    539 {
    540 	Elf64_Ehdr *ehdr;
    541 	Elf64_Shdr *shdr;
    542 	size_t min_addr = -1, max_addr = 0;
    543 	char *flat;
    544 	int i;
    545 
    546 	ehdr = (void *)elf;
    547 	shdr = (void *)(elf + le64_to_cpu(ehdr->e_shoff));
    548 
    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))
    554 			continue;
    555 
    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)) >
    559 			max_addr)
    560 			max_addr = le64_to_cpu(shdr->sh_addr) +
    561 				   le64_to_cpu(shdr->sh_size);
    562 	}
    563 
    564 	*load_addr = min_addr;
    565 	*flat_size = max_addr - min_addr;
    566 	flat = calloc(1, *flat_size);
    567 	if (!flat)
    568 		return NULL;
    569 
    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);
    574 
    575 		if (!shdr->sh_size || !shdr->sh_addr ||
    576 		    !(shdr->sh_flags & SHF_ALLOC))
    577 			continue;
    578 
    579 		if (shdr->sh_type != SHT_NOBITS)
    580 			memcpy(dst, src, le64_to_cpu(shdr->sh_size));
    581 	}
    582 
    583 	return flat;
    584 }
    585 
    586 static char *elf2flat32(char *elf, size_t *flat_size, size_t *load_addr)
    587 {
    588 	Elf32_Ehdr *ehdr;
    589 	Elf32_Shdr *shdr;
    590 	size_t min_addr = -1, max_addr = 0;
    591 	char *flat;
    592 	int i;
    593 
    594 	ehdr = (void *)elf;
    595 	shdr = (void *)(elf + le32_to_cpu(ehdr->e_shoff));
    596 
    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))
    602 			continue;
    603 
    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)) >
    607 			max_addr)
    608 			max_addr = le32_to_cpu(shdr->sh_addr) +
    609 				   le32_to_cpu(shdr->sh_size);
    610 	}
    611 
    612 	*load_addr = min_addr;
    613 	*flat_size = max_addr - min_addr;
    614 	flat = calloc(1, *flat_size);
    615 	if (!flat)
    616 		return NULL;
    617 
    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);
    622 
    623 		if (!shdr->sh_size || !shdr->sh_addr ||
    624 		    !(shdr->sh_flags & SHF_ALLOC))
    625 			continue;
    626 
    627 		if (shdr->sh_type != SHT_NOBITS)
    628 			memcpy(dst, src, le32_to_cpu(shdr->sh_size));
    629 	}
    630 
    631 	return flat;
    632 }
    633 
    634 static int bif_add_elf(struct bif_entry *bf)
    635 {
    636 	size_t size;
    637 	size_t elf_size;
    638 	char *elf;
    639 	char *flat;
    640 	size_t load_addr;
    641 	Elf32_Ehdr *ehdr32;
    642 	Elf64_Ehdr *ehdr64;
    643 
    644 	elf = read_full_file(bf->filename, &elf_size);
    645 	if (!elf)
    646 		return -1;
    647 
    648 	ehdr32 = (void *)elf;
    649 	ehdr64 = (void *)elf;
    650 
    651 	switch (ehdr32->e_ident[EI_CLASS]) {
    652 	case ELFCLASS32:
    653 		flat = elf2flat32(elf, &size, &load_addr);
    654 		bf->entry = le32_to_cpu(ehdr32->e_entry);
    655 		bf->flags |= 1ULL << BIF_FLAG_AARCH32;
    656 		break;
    657 	case ELFCLASS64:
    658 		flat = elf2flat64(elf, &size, &load_addr);
    659 		bf->entry = le64_to_cpu(ehdr64->e_entry);
    660 		break;
    661 	default:
    662 		printf("Unknown ELF class: %d\n", ehdr32->e_ident[EI_CLASS]);
    663 		return -1;
    664 	}
    665 
    666 	if (!flat)
    667 		return -1;
    668 
    669 	bf->load = load_addr;
    670 	if (!bf->dest_dev)
    671 		bf->dest_dev = PART_ATTR_DEST_DEVICE_PS;
    672 
    673 	bf->flags |= 1ULL << BIF_FLAG_ELF_FILE;
    674 	return bif_add_part(bf, flat, size);
    675 }
    676 
    677 static const struct bif_file_type bif_file_types[] = {
    678 	{
    679 		.name = "bitstream (.bit)",
    680 		.header = 0x00090ff0,
    681 		.add = bif_add_bit,
    682 	},
    683 
    684 	{
    685 		.name = "ELF",
    686 		.header = 0x7f454c46,
    687 		.add = bif_add_elf,
    688 	},
    689 
    690 	/* Anything else is a .bin file */
    691 	{
    692 		.name = ".bin",
    693 		.add = bif_add_bin,
    694 	},
    695 };
    696 
    697 static int bif_fsbl_config(struct bif_entry *fsbl_config,
    698 			   struct bif_entry *entries, int nr_entries)
    699 {
    700 	int i;
    701 	int config_set = 0;
    702 	struct {
    703 		const char *name;
    704 		uint64_t flags;
    705 		uint64_t dest_cpu;
    706 	} configs[] = {
    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 },
    715 	};
    716 
    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;
    721 		int j;
    722 
    723 		if (!(b->flags & (1ULL << BIF_FLAG_BOOTLOADER)))
    724 			continue;
    725 
    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;
    731 				config_set = 1;
    732 			}
    733 		}
    734 
    735 		if (!config_set) {
    736 			printf("ERROR: Unsupported fsbl_config: %s\n",
    737 			       config_attr);
    738 			return -1;
    739 		}
    740 	}
    741 
    742 	if (!config_set) {
    743 		printf("ERROR: fsbl_config w/o bootloader\n");
    744 		return -1;
    745 	}
    746 
    747 	return 0;
    748 }
    749 
    750 static const struct bif_flags *find_flag(char *str)
    751 {
    752 	const struct bif_flags *bf;
    753 	int i;
    754 
    755 	for (i = 0; i < ARRAY_SIZE(bif_flags); i++) {
    756 		bf = &bif_flags[i];
    757 		if (!strncmp(bf->name, str, strlen(bf->name)))
    758 			return bf;
    759 	}
    760 
    761 	printf("ERROR: Flag '%s' not found\n", str);
    762 
    763 	return NULL;
    764 }
    765 
    766 static int bif_open_file(struct bif_entry *entry)
    767 {
    768 	int fd = open(entry->filename, O_RDONLY);
    769 
    770 	if (fd < 0)
    771 		printf("Error opening file %s\n", entry->filename);
    772 
    773 	return fd;
    774 }
    775 
    776 static const struct bif_file_type *get_file_type(struct bif_entry *entry)
    777 {
    778 	int fd = bif_open_file(entry);
    779 	uint32_t header;
    780 	int i;
    781 
    782 	if (fd < 0)
    783 		return NULL;
    784 
    785 	if (read(fd, &header, sizeof(header)) != sizeof(header)) {
    786 		printf("Error reading file %s", entry->filename);
    787 		return NULL;
    788 	}
    789 
    790 	close(fd);
    791 
    792 	for (i = 0; i < ARRAY_SIZE(bif_file_types); i++) {
    793 		const struct bif_file_type *type = &bif_file_types[i];
    794 
    795 		if (!type->header)
    796 			return type;
    797 		if (type->header == be32_to_cpu(header))
    798 			return type;
    799 	}
    800 
    801 	return NULL;
    802 }
    803 
    804 #define NEXT_CHAR(str, chr) ({		\
    805 	char *_n = strchr(str, chr);	\
    806 	if (!_n)			\
    807 		goto err;		\
    808 	_n;				\
    809 })
    810 
    811 static char *skip_whitespace(char *str)
    812 {
    813 	while (*str == ' ' || *str == '\t')
    814 		str++;
    815 
    816 	return str;
    817 }
    818 
    819 int zynqmpbif_copy_image(int outfd, struct image_tool_params *mparams)
    820 {
    821 	char *bif, *bifp, *bifpn;
    822 	char *line;
    823 	struct bif_entry entries[32] = { { 0 } };
    824 	int nr_entries = 0;
    825 	struct bif_entry *entry = entries;
    826 	size_t len;
    827 	int i;
    828 	uint32_t csum;
    829 	int bldr = -1;
    830 
    831 	bif_init();
    832 
    833 	/* Read .bif input file */
    834 	bif = read_full_file(mparams->datafile, NULL);
    835 	if (!bif)
    836 		goto err;
    837 
    838 	/* Interpret .bif file */
    839 	bifp = bif;
    840 
    841 	/* A bif description starts with a { section */
    842 	bifp = NEXT_CHAR(bifp, '{') + 1;
    843 
    844 	/* Read every line */
    845 	while (1) {
    846 		bifpn = NEXT_CHAR(bifp, '\n');
    847 
    848 		if (bifpn[-1] == '\r')
    849 			bifpn[-1] = '\0';
    850 
    851 		*bifpn = '\0';
    852 		bifpn++;
    853 		line = bifp;
    854 
    855 		line = skip_whitespace(line);
    856 
    857 		/* Attributes? */
    858 		if (*line == '[') {
    859 			line++;
    860 			while (1) {
    861 				const struct bif_flags *bf;
    862 
    863 				line = skip_whitespace(line);
    864 				bf = find_flag(line);
    865 				if (!bf)
    866 					goto err;
    867 
    868 				line += strlen(bf->name);
    869 				if (bf->parse)
    870 					line = bf->parse(line, entry);
    871 				else
    872 					entry->flags |= 1ULL << bf->flag;
    873 
    874 				if (!line)
    875 					goto err;
    876 
    877 				/* Go to next attribute or quit */
    878 				if (*line == ']') {
    879 					line++;
    880 					break;
    881 				}
    882 				if (*line == ',')
    883 					line++;
    884 			}
    885 		}
    886 
    887 		/* End of image description */
    888 		if (*line == '}')
    889 			break;
    890 
    891 		if (*line) {
    892 			line = skip_whitespace(line);
    893 			entry->filename = line;
    894 			nr_entries++;
    895 			entry++;
    896 		}
    897 
    898 		/* Use next line */
    899 		bifp = bifpn;
    900 	}
    901 
    902 	for (i = 0; i < nr_entries; i++) {
    903 		debug("Entry flags=%#lx name=%s\n", entries[i].flags,
    904 		      entries[i].filename);
    905 	}
    906 
    907 	/*
    908 	 * Some entries are actually configuration option for other ones,
    909 	 * let's apply them in an intermediate step.
    910 	 */
    911 	for (i = 0; i < nr_entries; i++) {
    912 		struct bif_entry *entry = &entries[i];
    913 
    914 		if (entry->flags & (1ULL << BIF_FLAG_FSBL_CONFIG))
    915 			if (bif_fsbl_config(entry, entries, nr_entries))
    916 				goto err;
    917 	}
    918 
    919 	/* Make sure PMUFW comes before bootloader */
    920 	for (i = 0; i < nr_entries; i++) {
    921 		struct bif_entry *entry = &entries[i];
    922 
    923 		if (entry->flags & (1ULL << BIF_FLAG_BOOTLOADER))
    924 			bldr = i;
    925 		if (entry->flags & (1ULL << BIF_FLAG_PMUFW_IMAGE)) {
    926 			if (bldr >= 0) {
    927 				struct bif_entry tmp = *entry;
    928 
    929 				*entry = entries[bldr];
    930 				entries[bldr] = tmp;
    931 			}
    932 		}
    933 	}
    934 
    935 	for (i = 0; i < nr_entries; i++) {
    936 		struct bif_entry *entry = &entries[i];
    937 		const struct bif_file_type *type;
    938 		int r;
    939 
    940 		if (entry->flags & (1ULL << BIF_FLAG_FSBL_CONFIG))
    941 			continue;
    942 
    943 		type = get_file_type(entry);
    944 		if (!type)
    945 			goto err;
    946 
    947 		debug("type=%s file=%s\n", type->name, entry->filename);
    948 		r = type->add(entry);
    949 		if (r)
    950 			goto err;
    951 	}
    952 
    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);
    957 
    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);
    962 	}
    963 
    964 	/* Write headers and components */
    965 	if (lseek(outfd, 0, SEEK_SET) != 0)
    966 		goto err;
    967 
    968 	len = bif_output.data_len;
    969 	bifp = bif_output.data;
    970 	while (len) {
    971 		int r;
    972 
    973 		r = write(outfd, bifp, len);
    974 		if (r < 0)
    975 			goto err;
    976 		len -= r;
    977 		bifp += r;
    978 	}
    979 
    980 	return 0;
    981 
    982 err:
    983 	fprintf(stderr, "Error: Failed to create image.\n");
    984 	return -1;
    985 }
    986 
    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)
    990 {
    991 }
    992 
    993 static struct zynqmp_header zynqmpimage_header;
    994 
    995 U_BOOT_IMAGE_TYPE(
    996 	zynqmpbif,
    997 	"Xilinx ZynqMP Boot Image support (bif)",
    998 	sizeof(struct zynqmp_header),
    999 	(void *)&zynqmpimage_header,
   1000 	zynqmpbif_check_params,
   1001 	NULL,
   1002 	zynqmpimage_print_header,
   1003 	zynqmpbif_set_header,
   1004 	NULL,
   1005 	zynqmpbif_check_image_types,
   1006 	NULL,
   1007 	NULL
   1008 );
   1009