1/*
2 * Copyright (C) 2018 Alexander Graf <agraf@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
13struct 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
24enum 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
52struct bif_flags {
53	const char name[32];
54	uint64_t flag;
55	char *(*parse)(char *line, struct bif_entry *bf);
56};
57
58struct bif_file_type {
59	const char name[32];
60	uint32_t header;
61	int (*add)(struct bif_entry *bf);
62};
63
64struct 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
72struct bif_output bif_output;
73
74static 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
87static 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
105static int zynqmpbif_check_image_types(uint8_t type)
106{
107	return (type == IH_TYPE_ZYNQMPBIF) ? EXIT_SUCCESS : EXIT_FAILURE;
108}
109
110static 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
135static 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
150static 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
159static 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
168static 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
177static 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
193static 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
206static 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
240static 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
282static 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
298static 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
319static int bif_add_part(struct bif_entry *bf, const char *data, size_t len)
320{
321	size_t parthdr_offset = 0;
322	size_t len_padded = ROUND(len, 4);
323
324	struct partition_header parthdr = {
325		.len_enc = cpu_to_le32(len_padded / 4),
326		.len_unenc = cpu_to_le32(len_padded / 4),
327		.len = cpu_to_le32(len_padded / 4),
328		.entry_point = cpu_to_le64(bf->entry),
329		.load_address = cpu_to_le64(bf->load),
330	};
331	int r;
332	uint32_t csum;
333
334	if (len < len_padded) {
335		char *newdata = malloc(len_padded);
336		memcpy(newdata, data, len);
337		memset(newdata + len, 0, len_padded - len);
338		data = newdata;
339	}
340
341	if (bf->flags & (1ULL << BIF_FLAG_PMUFW_IMAGE))
342		return bif_add_pmufw(bf, data, len);
343
344	r = bif_add_blob(data, len, &bf->offset);
345	if (r)
346		return r;
347
348	parthdr.offset = cpu_to_le32(bf->offset / 4);
349
350	if (bf->flags & (1ULL << BIF_FLAG_BOOTLOADER)) {
351		if (bif_output.last_part) {
352			printf("ERROR: Bootloader expected before others\n");
353			return -1;
354		}
355
356		parthdr.offset = cpu_to_le32(bif_output.header->image_offset);
357		parthdr.len = cpu_to_le32((bf->offset + len -
358			bif_output.header->image_offset) / 4);
359		parthdr.len_enc = parthdr.len;
360		parthdr.len_unenc = parthdr.len;
361	}
362
363	/* Normalize EL */
364	bf->exp_lvl = bf->exp_lvl ? bf->exp_lvl - 1 : 3;
365	parthdr.attributes |= bf->exp_lvl << PART_ATTR_TARGET_EL_SHIFT;
366	parthdr.attributes |= bf->dest_dev;
367	parthdr.attributes |= bf->dest_cpu;
368	if (bf->flags & (1ULL << BIF_FLAG_TZ))
369		parthdr.attributes |= PART_ATTR_TZ_SECURE;
370	if (bf->flags & (1ULL << BIF_FLAG_PART_OWNER_UBOOT))
371		parthdr.attributes |= PART_ATTR_PART_OWNER_UBOOT;
372	switch (bf->dest_cpu) {
373	case PART_ATTR_DEST_CPU_NONE:
374	case PART_ATTR_DEST_CPU_A53_0:
375	case PART_ATTR_DEST_CPU_A53_1:
376	case PART_ATTR_DEST_CPU_A53_2:
377	case PART_ATTR_DEST_CPU_A53_3:
378		if (bf->flags & (1ULL << BIF_FLAG_AARCH32))
379			parthdr.attributes |= PART_ATTR_A53_EXEC_AARCH32;
380	}
381
382	csum = zynqmp_csum(&parthdr, &parthdr.checksum);
383	parthdr.checksum = cpu_to_le32(csum);
384
385	r = bif_add_blob(&parthdr, sizeof(parthdr), &parthdr_offset);
386	if (r)
387		return r;
388
389	/* Add image header table if not there yet */
390	if (!bif_output.imgheader) {
391		size_t imghdr_off = 0;
392		struct image_header_table imghdr = {
393			.version = cpu_to_le32(0x01020000),
394			.nr_parts = 0,
395		};
396
397		r = bif_add_blob(&imghdr, sizeof(imghdr), &imghdr_off);
398		if (r)
399			return r;
400
401		bif_output.header->image_header_table_offset = imghdr_off;
402		bif_output.imgheader = (void *)(bif_output.data + imghdr_off);
403	}
404
405	bif_output.imgheader->nr_parts = cpu_to_le32(le32_to_cpu(
406		bif_output.imgheader->nr_parts) + 1);
407
408	/* Link to this partition header */
409	if (bif_output.last_part) {
410		bif_output.last_part->next_partition_offset =
411			cpu_to_le32(parthdr_offset / 4);
412
413		/* Recalc checksum of last_part */
414		csum = zynqmp_csum(bif_output.last_part,
415				   &bif_output.last_part->checksum);
416		bif_output.last_part->checksum = cpu_to_le32(csum);
417	} else {
418		bif_output.imgheader->partition_header_offset =
419			cpu_to_le32(parthdr_offset / 4);
420	}
421	bif_output.last_part = (void *)(bif_output.data + parthdr_offset);
422
423	if (bf->flags & (1ULL << BIF_FLAG_BOOTLOADER)) {
424		bif_output.header->image_load = cpu_to_le32(bf->load);
425		if (!bif_output.header->image_offset)
426			bif_output.header->image_offset =
427				cpu_to_le32(bf->offset);
428		bif_output.header->image_size = cpu_to_le32(len_padded);
429		bif_output.header->image_stored_size = cpu_to_le32(len_padded);
430
431		bif_output.header->image_attributes &= ~HEADER_CPU_SELECT_MASK;
432		switch (bf->dest_cpu) {
433		default:
434		case PART_ATTR_DEST_CPU_A53_0:
435			if (bf->flags & BIF_FLAG_AARCH32)
436				bif_output.header->image_attributes |=
437					HEADER_CPU_SELECT_A53_32BIT;
438			else
439				bif_output.header->image_attributes |=
440					HEADER_CPU_SELECT_A53_64BIT;
441			break;
442		case PART_ATTR_DEST_CPU_R5_0:
443			bif_output.header->image_attributes |=
444				HEADER_CPU_SELECT_R5_SINGLE;
445			break;
446		case PART_ATTR_DEST_CPU_R5_L:
447			bif_output.header->image_attributes |=
448				HEADER_CPU_SELECT_R5_DUAL;
449			break;
450		}
451	}
452
453	return 0;
454}
455
456/* Add .bit bitstream */
457static int bif_add_bit(struct bif_entry *bf)
458{
459	char *bit = read_full_file(bf->filename, NULL);
460	char *bitbin;
461	uint8_t initial_header[] = { 0x00, 0x09, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f,
462				     0xf0, 0x0f, 0xf0, 0x00, 0x00, 0x01, 0x61 };
463	uint16_t len;
464	uint32_t bitlen;
465	int i;
466
467	if (!bit)
468		return -1;
469
470	/* Skip initial header */
471	if (memcmp(bit, initial_header, sizeof(initial_header)))
472		return -1;
473
474	bit += sizeof(initial_header);
475
476	/* Design name */
477	len = be16_to_cpu(*(uint16_t *)bit);
478	bit += sizeof(uint16_t);
479	debug("Design: %s\n", bit);
480	bit += len;
481
482	/* Device identifier */
483	if (*bit != 'b')
484		return -1;
485	bit++;
486	len = be16_to_cpu(*(uint16_t *)bit);
487	bit += sizeof(uint16_t);
488	debug("Device: %s\n", bit);
489	bit += len;
490
491	/* Date */
492	if (*bit != 'c')
493		return -1;
494	bit++;
495	len = be16_to_cpu(*(uint16_t *)bit);
496	bit += sizeof(uint16_t);
497	debug("Date: %s\n", bit);
498	bit += len;
499
500	/* Time */
501	if (*bit != 'd')
502		return -1;
503	bit++;
504	len = be16_to_cpu(*(uint16_t *)bit);
505	bit += sizeof(uint16_t);
506	debug("Time: %s\n", bit);
507	bit += len;
508
509	/* Bitstream length */
510	if (*bit != 'e')
511		return -1;
512	bit++;
513	bitlen = be32_to_cpu(*(uint32_t *)bit);
514	bit += sizeof(uint32_t);
515	bitbin = bit;
516
517	debug("Bitstream Length: 0x%x\n", bitlen);
518	for (i = 0; i < bitlen; i += sizeof(uint32_t)) {
519		uint32_t *bitbin32 = (uint32_t *)&bitbin[i];
520		*bitbin32 = __builtin_bswap32(*bitbin32);
521	}
522
523	if (!bf->dest_dev)
524		bf->dest_dev = PART_ATTR_DEST_DEVICE_PL;
525
526	bf->load = 0xffffffff;
527	bf->entry = 0;
528
529	bf->flags |= 1ULL << BIF_FLAG_BIT_FILE;
530	return bif_add_part(bf, bit, bitlen);
531}
532
533/* Add .bin bitstream */
534static int bif_add_bin(struct bif_entry *bf)
535{
536	size_t size;
537	char *bin = read_full_file(bf->filename, &size);
538
539	if (!bf->dest_dev)
540		bf->dest_dev = PART_ATTR_DEST_DEVICE_PS;
541
542	bf->flags |= 1ULL << BIF_FLAG_BIN_FILE;
543	return bif_add_part(bf, bin, size);
544}
545
546/* Add elf file */
547static char *elf2flat64(char *elf, size_t *flat_size, size_t *load_addr)
548{
549	Elf64_Ehdr *ehdr;
550	Elf64_Shdr *shdr;
551	size_t min_addr = -1, max_addr = 0;
552	char *flat;
553	int i;
554
555	ehdr = (void *)elf;
556	shdr = (void *)(elf + le64_to_cpu(ehdr->e_shoff));
557
558	/* Look for smallest / biggest address */
559	for (i = 0; i < le64_to_cpu(ehdr->e_shnum); i++, shdr++) {
560		if (!shdr->sh_size || !shdr->sh_addr ||
561		    !(shdr->sh_flags & SHF_ALLOC) ||
562		    (shdr->sh_type == SHT_NOBITS))
563			continue;
564
565		if (le64_to_cpu(shdr->sh_addr) < min_addr)
566			min_addr = le64_to_cpu(shdr->sh_addr);
567		if ((le64_to_cpu(shdr->sh_addr) + le64_to_cpu(shdr->sh_size)) >
568			max_addr)
569			max_addr = le64_to_cpu(shdr->sh_addr) +
570				   le64_to_cpu(shdr->sh_size);
571	}
572
573	*load_addr = min_addr;
574	*flat_size = max_addr - min_addr;
575	flat = calloc(1, *flat_size);
576	if (!flat)
577		return NULL;
578
579	shdr = (void *)(elf + le64_to_cpu(ehdr->e_shoff));
580	for (i = 0; i < le64_to_cpu(ehdr->e_shnum); i++, shdr++) {
581		char *dst = flat + le64_to_cpu(shdr->sh_addr) - min_addr;
582		char *src = elf + le64_to_cpu(shdr->sh_offset);
583
584		if (!shdr->sh_size || !shdr->sh_addr ||
585		    !(shdr->sh_flags & SHF_ALLOC))
586			continue;
587
588		if (shdr->sh_type != SHT_NOBITS)
589			memcpy(dst, src, le64_to_cpu(shdr->sh_size));
590	}
591
592	return flat;
593}
594
595static char *elf2flat32(char *elf, size_t *flat_size, size_t *load_addr)
596{
597	Elf32_Ehdr *ehdr;
598	Elf32_Shdr *shdr;
599	size_t min_addr = -1, max_addr = 0;
600	char *flat;
601	int i;
602
603	ehdr = (void *)elf;
604	shdr = (void *)(elf + le32_to_cpu(ehdr->e_shoff));
605
606	/* Look for smallest / biggest address */
607	for (i = 0; i < le32_to_cpu(ehdr->e_shnum); i++, shdr++) {
608		if (!shdr->sh_size || !shdr->sh_addr ||
609		    !(shdr->sh_flags & SHF_ALLOC) ||
610		    (shdr->sh_type == SHT_NOBITS))
611			continue;
612
613		if (le32_to_cpu(shdr->sh_addr) < min_addr)
614			min_addr = le32_to_cpu(shdr->sh_addr);
615		if ((le32_to_cpu(shdr->sh_addr) + le32_to_cpu(shdr->sh_size)) >
616			max_addr)
617			max_addr = le32_to_cpu(shdr->sh_addr) +
618				   le32_to_cpu(shdr->sh_size);
619	}
620
621	*load_addr = min_addr;
622	*flat_size = max_addr - min_addr;
623	flat = calloc(1, *flat_size);
624	if (!flat)
625		return NULL;
626
627	shdr = (void *)(elf + le32_to_cpu(ehdr->e_shoff));
628	for (i = 0; i < le32_to_cpu(ehdr->e_shnum); i++, shdr++) {
629		char *dst = flat + le32_to_cpu(shdr->sh_addr) - min_addr;
630		char *src = elf + le32_to_cpu(shdr->sh_offset);
631
632		if (!shdr->sh_size || !shdr->sh_addr ||
633		    !(shdr->sh_flags & SHF_ALLOC))
634			continue;
635
636		if (shdr->sh_type != SHT_NOBITS)
637			memcpy(dst, src, le32_to_cpu(shdr->sh_size));
638	}
639
640	return flat;
641}
642
643static int bif_add_elf(struct bif_entry *bf)
644{
645	size_t size;
646	size_t elf_size;
647	char *elf;
648	char *flat;
649	size_t load_addr;
650	Elf32_Ehdr *ehdr32;
651	Elf64_Ehdr *ehdr64;
652
653	elf = read_full_file(bf->filename, &elf_size);
654	if (!elf)
655		return -1;
656
657	ehdr32 = (void *)elf;
658	ehdr64 = (void *)elf;
659
660	switch (ehdr32->e_ident[EI_CLASS]) {
661	case ELFCLASS32:
662		flat = elf2flat32(elf, &size, &load_addr);
663		bf->entry = le32_to_cpu(ehdr32->e_entry);
664		bf->flags |= 1ULL << BIF_FLAG_AARCH32;
665		break;
666	case ELFCLASS64:
667		flat = elf2flat64(elf, &size, &load_addr);
668		bf->entry = le64_to_cpu(ehdr64->e_entry);
669		break;
670	default:
671		printf("Unknown ELF class: %d\n", ehdr32->e_ident[EI_CLASS]);
672		return -1;
673	}
674
675	if (!flat)
676		return -1;
677
678	bf->load = load_addr;
679	if (!bf->dest_dev)
680		bf->dest_dev = PART_ATTR_DEST_DEVICE_PS;
681
682	bf->flags |= 1ULL << BIF_FLAG_ELF_FILE;
683	return bif_add_part(bf, flat, size);
684}
685
686static const struct bif_file_type bif_file_types[] = {
687	{
688		.name = "bitstream (.bit)",
689		.header = 0x00090ff0,
690		.add = bif_add_bit,
691	},
692
693	{
694		.name = "ELF",
695		.header = 0x7f454c46,
696		.add = bif_add_elf,
697	},
698
699	/* Anything else is a .bin file */
700	{
701		.name = ".bin",
702		.add = bif_add_bin,
703	},
704};
705
706static int bif_fsbl_config(struct bif_entry *fsbl_config,
707			   struct bif_entry *entries, int nr_entries)
708{
709	int i;
710	int config_set = 0;
711	struct {
712		const char *name;
713		uint64_t flags;
714		uint64_t dest_cpu;
715	} configs[] = {
716		{ .name = "a5x_x64", .dest_cpu = PART_ATTR_DEST_CPU_A53_0 },
717		{ .name = "a53_x64", .dest_cpu = PART_ATTR_DEST_CPU_A53_0 },
718		{ .name = "a5x_x32", .dest_cpu = PART_ATTR_DEST_CPU_A53_0,
719				     .flags = 1ULL << BIF_FLAG_AARCH32 },
720		{ .name = "a53_x32", .dest_cpu = PART_ATTR_DEST_CPU_A53_0,
721				     .flags = 1ULL << BIF_FLAG_AARCH32 },
722		{ .name = "r5_single", .dest_cpu = PART_ATTR_DEST_CPU_R5_0 },
723		{ .name = "r5_dual", .dest_cpu = PART_ATTR_DEST_CPU_R5_L },
724	};
725
726	/* Set target CPU of bootloader entry */
727	for (i = 0; i < nr_entries; i++) {
728		struct bif_entry *b = &entries[i];
729		const char *config_attr = fsbl_config->filename;
730		int j;
731
732		if (!(b->flags & (1ULL << BIF_FLAG_BOOTLOADER)))
733			continue;
734
735		for (j = 0; j < ARRAY_SIZE(configs); j++) {
736			if (!strncmp(config_attr, configs[j].name,
737				     strlen(configs[j].name))) {
738				b->dest_cpu = configs[j].dest_cpu;
739				b->flags |= configs[j].flags;
740				config_set = 1;
741			}
742		}
743
744		if (!config_set) {
745			printf("ERROR: Unsupported fsbl_config: %s\n",
746			       config_attr);
747			return -1;
748		}
749	}
750
751	if (!config_set) {
752		printf("ERROR: fsbl_config w/o bootloader\n");
753		return -1;
754	}
755
756	return 0;
757}
758
759static const struct bif_flags *find_flag(char *str)
760{
761	const struct bif_flags *bf;
762	int i;
763
764	for (i = 0; i < ARRAY_SIZE(bif_flags); i++) {
765		bf = &bif_flags[i];
766		if (!strncmp(bf->name, str, strlen(bf->name)))
767			return bf;
768	}
769
770	printf("ERROR: Flag '%s' not found\n", str);
771
772	return NULL;
773}
774
775static int bif_open_file(struct bif_entry *entry)
776{
777	int fd = open(entry->filename, O_RDONLY);
778
779	if (fd < 0)
780		printf("Error opening file %s\n", entry->filename);
781
782	return fd;
783}
784
785static const struct bif_file_type *get_file_type(struct bif_entry *entry)
786{
787	int fd = bif_open_file(entry);
788	uint32_t header;
789	int i;
790
791	if (fd < 0)
792		return NULL;
793
794	if (read(fd, &header, sizeof(header)) != sizeof(header)) {
795		printf("Error reading file %s", entry->filename);
796		return NULL;
797	}
798
799	close(fd);
800
801	for (i = 0; i < ARRAY_SIZE(bif_file_types); i++) {
802		const struct bif_file_type *type = &bif_file_types[i];
803
804		if (!type->header)
805			return type;
806		if (type->header == be32_to_cpu(header))
807			return type;
808	}
809
810	return NULL;
811}
812
813#define NEXT_CHAR(str, chr) ({		\
814	char *_n = strchr(str, chr);	\
815	if (!_n)			\
816		goto err;		\
817	_n;				\
818})
819
820static char *skip_whitespace(char *str)
821{
822	while (*str == ' ' || *str == '\t')
823		str++;
824
825	return str;
826}
827
828int zynqmpbif_copy_image(int outfd, struct image_tool_params *mparams)
829{
830	char *bif, *bifp, *bifpn;
831	char *line;
832	struct bif_entry entries[32] = { { 0 } };
833	int nr_entries = 0;
834	struct bif_entry *entry = entries;
835	size_t len;
836	int i;
837	uint32_t csum;
838	int bldr = -1;
839
840	bif_init();
841
842	/* Read .bif input file */
843	bif = read_full_file(mparams->datafile, NULL);
844	if (!bif)
845		goto err;
846
847	/* Interpret .bif file */
848	bifp = bif;
849
850	/* A bif description starts with a { section */
851	bifp = NEXT_CHAR(bifp, '{') + 1;
852
853	/* Read every line */
854	while (1) {
855		bifpn = NEXT_CHAR(bifp, '\n');
856
857		if (bifpn[-1] == '\r')
858			bifpn[-1] = '\0';
859
860		*bifpn = '\0';
861		bifpn++;
862		line = bifp;
863
864		line = skip_whitespace(line);
865
866		/* Attributes? */
867		if (*line == '[') {
868			line++;
869			while (1) {
870				const struct bif_flags *bf;
871
872				line = skip_whitespace(line);
873				bf = find_flag(line);
874				if (!bf)
875					goto err;
876
877				line += strlen(bf->name);
878				if (bf->parse)
879					line = bf->parse(line, entry);
880				else
881					entry->flags |= 1ULL << bf->flag;
882
883				if (!line)
884					goto err;
885
886				/* Go to next attribute or quit */
887				if (*line == ']') {
888					line++;
889					break;
890				}
891				if (*line == ',')
892					line++;
893			}
894		}
895
896		/* End of image description */
897		if (*line == '}')
898			break;
899
900		if (*line) {
901			line = skip_whitespace(line);
902			entry->filename = line;
903			nr_entries++;
904			entry++;
905		}
906
907		/* Use next line */
908		bifp = bifpn;
909	}
910
911	for (i = 0; i < nr_entries; i++) {
912		debug("Entry flags=%#lx name=%s\n", entries[i].flags,
913		      entries[i].filename);
914	}
915
916	/*
917	 * Some entries are actually configuration option for other ones,
918	 * let's apply them in an intermediate step.
919	 */
920	for (i = 0; i < nr_entries; i++) {
921		struct bif_entry *entry = &entries[i];
922
923		if (entry->flags & (1ULL << BIF_FLAG_FSBL_CONFIG))
924			if (bif_fsbl_config(entry, entries, nr_entries))
925				goto err;
926	}
927
928	/* Make sure PMUFW comes before bootloader */
929	for (i = 0; i < nr_entries; i++) {
930		struct bif_entry *entry = &entries[i];
931
932		if (entry->flags & (1ULL << BIF_FLAG_BOOTLOADER))
933			bldr = i;
934		if (entry->flags & (1ULL << BIF_FLAG_PMUFW_IMAGE)) {
935			if (bldr >= 0) {
936				struct bif_entry tmp = *entry;
937
938				*entry = entries[bldr];
939				entries[bldr] = tmp;
940			}
941		}
942	}
943
944	for (i = 0; i < nr_entries; i++) {
945		struct bif_entry *entry = &entries[i];
946		const struct bif_file_type *type;
947		int r;
948
949		if (entry->flags & (1ULL << BIF_FLAG_FSBL_CONFIG))
950			continue;
951
952		type = get_file_type(entry);
953		if (!type)
954			goto err;
955
956		debug("type=%s file=%s\n", type->name, entry->filename);
957		r = type->add(entry);
958		if (r)
959			goto err;
960	}
961
962	/* Calculate checksums */
963	csum = zynqmp_csum(&bif_output.header->width_detection,
964			   &bif_output.header->checksum);
965	bif_output.header->checksum = cpu_to_le32(csum);
966
967	if (bif_output.imgheader) {
968		csum = zynqmp_csum(bif_output.imgheader,
969				   &bif_output.imgheader->checksum);
970		bif_output.imgheader->checksum = cpu_to_le32(csum);
971	}
972
973	/* Write headers and components */
974	if (lseek(outfd, 0, SEEK_SET) != 0)
975		goto err;
976
977	len = bif_output.data_len;
978	bifp = bif_output.data;
979	while (len) {
980		int r;
981
982		r = write(outfd, bifp, len);
983		if (r < 0)
984			goto err;
985		len -= r;
986		bifp += r;
987	}
988
989	return 0;
990
991err:
992	fprintf(stderr, "Error: Failed to create image.\n");
993	return -1;
994}
995
996/* Needs to be stubbed out so we can print after creation */
997static void zynqmpbif_set_header(void *ptr, struct stat *sbuf, int ifd,
998				 struct image_tool_params *params)
999{
1000}
1001
1002static struct zynqmp_header zynqmpimage_header;
1003
1004U_BOOT_IMAGE_TYPE(
1005	zynqmpbif,
1006	"Xilinx ZynqMP Boot Image support (bif)",
1007	sizeof(struct zynqmp_header),
1008	(void *)&zynqmpimage_header,
1009	zynqmpbif_check_params,
1010	NULL,
1011	zynqmpimage_print_header,
1012	zynqmpbif_set_header,
1013	NULL,
1014	zynqmpbif_check_image_types,
1015	NULL,
1016	NULL
1017);
1018