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