xref: /openbmc/u-boot/tools/zynqmpbif.c (revision dbb0696b)
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 
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 	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 */
457 static 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 = __swab32(*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 */
534 static 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 */
547 static 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 
595 static 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 
643 static 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 
686 static 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 
706 static 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 
759 static 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 
775 static 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 
785 static 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 
820 static char *skip_whitespace(char *str)
821 {
822 	while (*str == ' ' || *str == '\t')
823 		str++;
824 
825 	return str;
826 }
827 
828 int 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 
991 err:
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 */
997 static void zynqmpbif_set_header(void *ptr, struct stat *sbuf, int ifd,
998 				 struct image_tool_params *params)
999 {
1000 }
1001 
1002 static struct zynqmp_header zynqmpimage_header;
1003 
1004 U_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