xref: /openbmc/u-boot/tools/zynqmpbif.c (revision ce0d1e48165fdd3bde4bb431f1d2e100b1617a6e)
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  
zynqmp_csum(void * start,void * end)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  
zynqmpbif_check_params(struct image_tool_params * params)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  
zynqmpbif_check_image_types(uint8_t type)105  static int zynqmpbif_check_image_types(uint8_t type)
106  {
107  	return (type == IH_TYPE_ZYNQMPBIF) ? EXIT_SUCCESS : EXIT_FAILURE;
108  }
109  
parse_dest_cpu(char * line,struct bif_entry * bf)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  
parse_el(char * line,struct bif_entry * bf)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  
parse_load(char * line,struct bif_entry * bf)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  
parse_entry(char * line,struct bif_entry * bf)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  
parse_offset(char * line,struct bif_entry * bf)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  
parse_partition_owner(char * line,struct bif_entry * bf)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  
read_full_file(const char * filename,size_t * size)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  
bif_add_blob(const void * data,size_t len,size_t * offset)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  
bif_init(void)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  
bif_add_pmufw(struct bif_entry * bf,const char * data,size_t len)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  
bif_add_part(struct bif_entry * bf,const char * data,size_t len)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 */
bif_add_bit(struct bif_entry * bf)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 */
bif_add_bin(struct bif_entry * bf)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 */
elf2flat64(char * elf,size_t * flat_size,size_t * load_addr)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  
elf2flat32(char * elf,size_t * flat_size,size_t * load_addr)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  
bif_add_elf(struct bif_entry * bf)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  
bif_fsbl_config(struct bif_entry * fsbl_config,struct bif_entry * entries,int nr_entries)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  
find_flag(char * str)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  
bif_open_file(struct bif_entry * entry)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  
get_file_type(struct bif_entry * entry)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  
skip_whitespace(char * str)820  static char *skip_whitespace(char *str)
821  {
822  	while (*str == ' ' || *str == '\t')
823  		str++;
824  
825  	return str;
826  }
827  
zynqmpbif_copy_image(int outfd,struct image_tool_params * mparams)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 */
zynqmpbif_set_header(void * ptr,struct stat * sbuf,int ifd,struct image_tool_params * params)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