arm64: zynqmp: add tool to minimize psu_init_gpl.c files
[platform/kernel/u-boot.git] / tools / zynqmpbif.c
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 );