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