On 12.4.2018 15:48, Alexander Graf wrote:
> The officially described way to generate boot.bin files for ZynqMP is to
> describe the contents of the target binary using a file of the "bif" format.
> This file then links to other files that all get packed into a bootable image.
> 
> This patch adds support to read such a .bif file and generate a respective
> ZynqMP boot.bin file that can include the normal image and pmu files, but also
> supports image partitions now. This makes it a handy replacement for the
> proprietary "bootgen" utility that is currently used to generate boot.bin
> files with FSBL.
> 
> Signed-off-by: Alexander Graf <ag...@suse.de>
> 
> ---
> 
> v2 -> v3:
> 
>   - zero initialize header
>   - reduce default debug verbosity
> ---
>  common/image.c      |   1 +
>  include/image.h     |   1 +
>  tools/Makefile      |   1 +
>  tools/imagetool.h   |   1 +
>  tools/mkimage.c     |   3 +
>  tools/zynqmpbif.c   | 839 
> ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  tools/zynqmpimage.c |   4 +-
>  tools/zynqmpimage.h |   3 +
>  8 files changed, 851 insertions(+), 2 deletions(-)
>  create mode 100644 tools/zynqmpbif.c
> 
> diff --git a/common/image.c b/common/image.c
> index e1c50eb25d..f30dfa229b 100644
> --- a/common/image.c
> +++ b/common/image.c
> @@ -159,6 +159,7 @@ static const table_entry_t uimage_type[] = {
>       {       IH_TYPE_VYBRIDIMAGE, "vybridimage",  "Vybrid Boot Image", },
>       {       IH_TYPE_ZYNQIMAGE,  "zynqimage",  "Xilinx Zynq Boot Image" },
>       {       IH_TYPE_ZYNQMPIMAGE, "zynqmpimage", "Xilinx ZynqMP Boot Image" 
> },
> +     {       IH_TYPE_ZYNQMPBIF,  "zynqmpbif",  "Xilinx ZynqMP Boot Image 
> (bif)" },
>       {       IH_TYPE_FPGA,       "fpga",       "FPGA Image" },
>       {       IH_TYPE_TEE,        "tee",        "Trusted Execution 
> Environment Image",},
>       {       IH_TYPE_FIRMWARE_IVT, "firmware_ivt", "Firmware with HABv4 IVT" 
> },
> diff --git a/include/image.h b/include/image.h
> index a579c5f509..c5af912aeb 100644
> --- a/include/image.h
> +++ b/include/image.h
> @@ -269,6 +269,7 @@ enum {
>       IH_TYPE_RKSPI,                  /* Rockchip SPI image           */
>       IH_TYPE_ZYNQIMAGE,              /* Xilinx Zynq Boot Image */
>       IH_TYPE_ZYNQMPIMAGE,            /* Xilinx ZynqMP Boot Image */
> +     IH_TYPE_ZYNQMPBIF,              /* Xilinx ZynqMP Boot Image (bif) */
>       IH_TYPE_FPGA,                   /* FPGA Image */
>       IH_TYPE_VYBRIDIMAGE,    /* VYBRID .vyb Image */
>       IH_TYPE_TEE,            /* Trusted Execution Environment OS Image */
> diff --git a/tools/Makefile b/tools/Makefile
> index 8143c25666..204685ec9e 100644
> --- a/tools/Makefile
> +++ b/tools/Makefile
> @@ -113,6 +113,7 @@ dumpimage-mkimage-objs := aisimage.o \
>                       ublimage.o \
>                       zynqimage.o \
>                       zynqmpimage.o \
> +                     zynqmpbif.o \
>                       $(LIBFDT_OBJS) \
>                       gpimage.o \
>                       gpimage-common.o \
> diff --git a/tools/imagetool.h b/tools/imagetool.h
> index e67de9b5ad..d78a9458f4 100644
> --- a/tools/imagetool.h
> +++ b/tools/imagetool.h
> @@ -232,6 +232,7 @@ time_t imagetool_get_source_date(
>  
>  
>  void pbl_load_uboot(int fd, struct image_tool_params *mparams);
> +void zynqmpbif_copy_image(int fd, struct image_tool_params *mparams);

This should return value which you will check

>  
>  #define ___cat(a, b) a ## b
>  #define __cat(a, b) ___cat(a, b)
> diff --git a/tools/mkimage.c b/tools/mkimage.c
> index 4e561820e7..72183f5f2b 100644
> --- a/tools/mkimage.c
> +++ b/tools/mkimage.c
> @@ -514,6 +514,9 @@ int main(int argc, char **argv)
>               } else if (params.type == IH_TYPE_PBLIMAGE) {
>                       /* PBL has special Image format, implements its' own */
>                       pbl_load_uboot(ifd, &params);
> +             } else if (params.type == IH_TYPE_ZYNQMPBIF) {
> +                     /* Image file is meta, walk through actual targets */
> +                     zynqmpbif_copy_image(ifd, &params);

The same here because if there is for example comment in bif format
which is permitted than you need to error out.

>               } else {
>                       copy_file(ifd, params.datafile, pad_len);
>               }
> diff --git a/tools/zynqmpbif.c b/tools/zynqmpbif.c
> new file mode 100644
> index 0000000000..d60eff1d8b
> --- /dev/null
> +++ b/tools/zynqmpbif.c
> @@ -0,0 +1,839 @@
> +/*
> + * Copyright (C) 2018 Alexander Graf <ag...@suse.de>
> + *
> + * SPDX-License-Identifier:  GPL-2.0+
> + */
> +
> +#include "imagetool.h"
> +#include "mkimage.h"
> +#include "zynqmpimage.h"
> +#include <elf.h>
> +#include <image.h>
> +
> +struct bif_entry {
> +     const char *filename;
> +     uint64_t flags;
> +     uint64_t dest_cpu;
> +     uint64_t exp_lvl;
> +     uint64_t dest_dev;
> +     uint64_t load;
> +     uint64_t entry;
> +};
> +
> +enum bif_flag {
> +     BIF_FLAG_AESKEYFILE,
> +     BIF_FLAG_INIT,
> +     BIF_FLAG_UDF_BH,
> +     BIF_FLAG_HEADERSIGNATURE,
> +     BIF_FLAG_PPKFILE,
> +     BIF_FLAG_PSKFILE,
> +     BIF_FLAG_SPKFILE,
> +     BIF_FLAG_SSKFILE,
> +     BIF_FLAG_SPKSIGNATURE,
> +     BIF_FLAG_FSBL_CONFIG,
> +     BIF_FLAG_AUTH_PARAMS,
> +     BIF_FLAG_KEYSRC_ENCRYPTION,
> +     BIF_FLAG_PMUFW_IMAGE,
> +     BIF_FLAG_BOOTLOADER,
> +     BIF_FLAG_TZ,
> +     BIF_FLAG_BH_KEY_IV,
> +     BIF_FLAG_BH_KEYFILE,
> +     BIF_FLAG_PUF_FILE,
> +
> +     /* Internal flags */
> +     BIF_FLAG_BIT_FILE,
> +     BIF_FLAG_ELF_FILE,
> +     BIF_FLAG_BIN_FILE,
> +};
> +
> +struct bif_flags {
> +     const char name[32];
> +     uint64_t flag;
> +     char *(*parse)(char *line, struct bif_entry *bf);
> +};
> +
> +struct bif_file_type {
> +     const char name[32];
> +     uint32_t header;
> +     int (*add)(struct bif_entry *bf);
> +};
> +
> +struct bif_output {
> +     size_t data_len;
> +     char *data;
> +     struct image_header_table *imgheader;
> +     struct zynqmp_header *header;
> +     struct partition_header *last_part;
> +};
> +
> +struct bif_output bif_output;
> +
> +static uint32_t zynqmp_csum(void *start, void *end)
> +{
> +     uint32_t checksum = 0;
> +     uint32_t *ptr32 = start;
> +
> +     while (ptr32 != end) {
> +             checksum += le32_to_cpu(*ptr32);
> +             ptr32++;
> +     }
> +
> +     return ~checksum;
> +}
> +
> +static int zynqmpbif_check_params(struct image_tool_params *params)
> +{
> +     if (!params)
> +             return 0;
> +
> +     if (params->addr != 0x0) {
> +             fprintf(stderr, "Error: Load Address can not be specified.\n");
> +             return -1;
> +     }
> +
> +     if (params->eflag) {
> +             fprintf(stderr, "Error: Entry Point can not be specified.\n");
> +             return -1;
> +     }
> +
> +     return !(params->lflag || params->dflag);
> +}
> +
> +static int zynqmpbif_check_image_types(uint8_t type)
> +{
> +     return (type == IH_TYPE_ZYNQMPBIF) ? EXIT_SUCCESS : EXIT_FAILURE;
> +}
> +
> +static char *parse_dest_cpu(char *line, struct bif_entry *bf)
> +{
> +     int i;
> +
> +     for (i = 0; i < ARRAY_SIZE(dest_cpus); i++) {
> +             if (!strncmp(line, dest_cpus[i], strlen(dest_cpus[i]))) {
> +                     bf->dest_cpu = i;
> +                     return line + strlen(dest_cpus[i]);
> +             }
> +     }
> +
> +     return line;
> +}
> +
> +static char *parse_el(char *line, struct bif_entry *bf)
> +{
> +     const char *dest_els[] = { "none", "el-0", "el-1", "el-2", "el-3" };
> +     int i;
> +
> +     for (i = 0; i < ARRAY_SIZE(dest_els); i++) {
> +             if (!strncmp(line, dest_els[i], strlen(dest_els[i]))) {
> +                     bf->exp_lvl = i;
> +                     return line + strlen(dest_els[i]);
> +             }
> +     }
> +
> +     return line;
> +}
> +
> +static char *parse_load(char *line, struct bif_entry *bf)
> +{
> +     char *endptr;
> +
> +     bf->load = strtoll(line, &endptr, 0);
> +
> +     return endptr;
> +}
> +
> +static char *parse_entry(char *line, struct bif_entry *bf)
> +{
> +     char *endptr;
> +
> +     bf->entry = strtoll(line, &endptr, 0);
> +
> +     return endptr;
> +}
> +
> +static const struct bif_flags bif_flags[] = {
> +     { "fsbl_config", BIF_FLAG_FSBL_CONFIG },
> +     { "trustzone", BIF_FLAG_TZ },
> +     { "pmufw_image", BIF_FLAG_PMUFW_IMAGE },
> +     { "bootloader", BIF_FLAG_BOOTLOADER },
> +     { "destination_cpu=", 0, parse_dest_cpu },
> +     { "exception_level=", 0, parse_el },
> +     { "load=", 0, parse_load },
> +     { "startup=", 0, parse_entry },
> +};
> +
> +static char *read_full_file(const char *filename, size_t *size)
> +{
> +     char *buf, *bufp;
> +     struct stat sbuf;
> +     int len = 0, r, fd;
> +
> +     fd = open(filename, O_RDONLY);
> +     if (fd < 0)
> +             return NULL;
> +
> +     if (fstat(fd, &sbuf) < 0)
> +             return NULL;
> +
> +     if (size)
> +             *size = sbuf.st_size;
> +
> +     bufp = buf = malloc(sbuf.st_size);
> +     if (!buf)
> +             return NULL;
> +
> +     while (len < sbuf.st_size) {
> +             r = read(fd, bufp, sbuf.st_size - len);
> +             if (r < 0)
> +                     return NULL;
> +             len += r;
> +             bufp += r;
> +     }
> +
> +     close(fd);
> +
> +     return buf;
> +}
> +
> +static int bif_add_blob(const void *data, size_t len, size_t *offset)
> +{
> +     size_t new_size = ROUND(bif_output.data_len + len, 64);
> +     uintptr_t header_off;
> +     uintptr_t last_part_off;
> +     uintptr_t imgheader_off;
> +     uintptr_t old_data = (uintptr_t)bif_output.data;
> +
> +     header_off = (uintptr_t)bif_output.header - old_data;
> +     last_part_off = (uintptr_t)bif_output.last_part - old_data;
> +     imgheader_off = (uintptr_t)bif_output.imgheader - old_data;
> +
> +     bif_output.data = realloc(bif_output.data, new_size);
> +     memcpy(bif_output.data + bif_output.data_len, data, len);
> +     if (offset)
> +             *offset = bif_output.data_len;
> +     bif_output.data_len = new_size;
> +
> +     /* Readjust internal pointers */
> +     if (bif_output.header)
> +             bif_output.header = (void*)(bif_output.data + header_off);
> +     if (bif_output.last_part)
> +             bif_output.last_part = (void*)(bif_output.data + last_part_off);
> +     if (bif_output.imgheader)
> +             bif_output.imgheader = (void*)(bif_output.data + imgheader_off);
> +
> +     return 0;
> +}
> +
> +static int bif_init(void)
> +{
> +     struct zynqmp_header header = { { 0 } };
> +     int r;
> +
> +     zynqmpimage_default_header(&header);
> +
> +     r = bif_add_blob(&header, sizeof(header), NULL);
> +     if (r)
> +             return r;
> +
> +     bif_output.header = (void*)bif_output.data;
> +
> +     return 0;
> +}
> +
> +static int bif_add_pmufw(struct bif_entry *bf, const char *data, size_t len)
> +{
> +     size_t offset;
> +
> +     if (bif_output.header->image_offset) {
> +             printf("PMUFW expected before bootloader in your .bif file!\n");
> +             return -1;
> +     }
> +
> +     bif_add_blob(data, len, &offset);
> +     len = ROUND(len, 64);
> +     bif_output.header->pfw_image_length = cpu_to_le32(len);
> +     bif_output.header->total_pfw_image_length = cpu_to_le32(len);
> +     bif_output.header->image_offset = cpu_to_le32(offset);
> +
> +     return 0;
> +}
> +
> +static int bif_add_part(struct bif_entry *bf, const char *data, size_t len)
> +{
> +     size_t parthdr_offset, part_offset;
> +     struct partition_header parthdr = {
> +             .len_enc = cpu_to_le32(len / 4),
> +             .len_unenc = cpu_to_le32(len / 4),
> +             .len = cpu_to_le32(len / 4),
> +             .entry_point = cpu_to_le64(bf->entry),
> +             .load_address = cpu_to_le64(bf->load),
> +     };
> +     int r;
> +     uint32_t csum;
> +
> +     if (bf->flags & (1ULL << BIF_FLAG_PMUFW_IMAGE))
> +             return bif_add_pmufw(bf, data, len);
> +
> +     bif_add_blob(data, len, &part_offset);
> +     parthdr.offset = cpu_to_le32(part_offset / 4);
> +
> +     if (bf->flags & (1ULL << BIF_FLAG_BOOTLOADER)) {
> +             if (bif_output.last_part) {
> +                     printf("ERROR: Bootloader needs to come as first 
> non-PMU partition");
> +                     return -1;
> +             }
> +
> +             parthdr.offset = cpu_to_le32(bif_output.header->image_offset);
> +             parthdr.len = cpu_to_le32((part_offset + len -
> +                     bif_output.header->image_offset) / 4);
> +             parthdr.len_enc = parthdr.len;
> +             parthdr.len_unenc = parthdr.len;
> +     }
> +
> +     /* Normalize EL */
> +     bf->exp_lvl = bf->exp_lvl ? bf->exp_lvl - 1 : 3;
> +     parthdr.attributes |= bf->exp_lvl << PART_ATTR_TARGET_EL_SHIFT;
> +     parthdr.attributes |= bf->dest_dev;
> +     parthdr.attributes |= bf->dest_cpu << PART_ATTR_DEST_CPU_SHIFT;
> +     if (bf->flags & (1ULL << BIF_FLAG_TZ))
> +             parthdr.attributes |= PART_ATTR_TZ_SECURE;
> +
> +     csum = zynqmp_csum(&parthdr, &parthdr.checksum);
> +     parthdr.checksum = cpu_to_le32(csum);
> +
> +     r = bif_add_blob(&parthdr, sizeof(parthdr), &parthdr_offset);
> +     if (r)
> +             return r;
> +
> +     /* Add image header table if not there yet */
> +     if (!bif_output.imgheader) {
> +             size_t imghdr_off;
> +             struct image_header_table imghdr = {
> +                     .version = cpu_to_le32(0x01020000),
> +                     .nr_parts = 0,
> +             };
> +
> +             r = bif_add_blob(&imghdr, sizeof(imghdr), &imghdr_off);
> +             if (r)
> +                     return r;
> +
> +             bif_output.header->image_header_table_offset = imghdr_off;
> +             bif_output.imgheader = (void*)(bif_output.data + imghdr_off);
> +     }
> +
> +     bif_output.imgheader->nr_parts = cpu_to_le32(le32_to_cpu(
> +             bif_output.imgheader->nr_parts) + 1);
> +
> +     /* Link to this partition header */
> +     if (bif_output.last_part) {
> +             bif_output.last_part->next_partition_offset =
> +                     cpu_to_le32(parthdr_offset / 4);
> +
> +             /* Recalc checksum of last_part */
> +             csum = zynqmp_csum(bif_output.last_part,
> +                                &bif_output.last_part->checksum);
> +             bif_output.last_part->checksum = cpu_to_le32(csum);
> +     } else {
> +             bif_output.imgheader->partition_header_offset =
> +                     cpu_to_le32(parthdr_offset / 4);
> +     }
> +     bif_output.last_part = (void*)(bif_output.data + parthdr_offset);
> +
> +     if (bf->flags & (1ULL << BIF_FLAG_BOOTLOADER)) {
> +             bif_output.header->image_load = cpu_to_le32(bf->load);
> +             if (!bif_output.header->image_offset)
> +                     bif_output.header->image_offset =
> +                             cpu_to_le32(part_offset);
> +             bif_output.header->image_size = cpu_to_le32(len);
> +             bif_output.header->image_stored_size = cpu_to_le32(len);
> +     }
> +
> +     return 0;
> +}
> +
> +/* Add .bit bitstream */
> +static int bif_add_bit(struct bif_entry *bf)
> +{
> +     char *bit = read_full_file(bf->filename, NULL);
> +     char *bitbin;
> +     uint8_t initial_header[] = { 0x00, 0x09, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f,
> +                                  0xf0, 0x0f, 0xf0, 0x00, 0x00, 0x01, 0x61 };
> +     uint16_t len;
> +     uint32_t bitlen;
> +     int i;
> +
> +     if (!bit)
> +             return -1;
> +
> +     /* Skip initial header */
> +     if (memcmp(bit, initial_header, sizeof(initial_header)))
> +             return -1;
> +
> +     bit += sizeof(initial_header);
> +
> +     /* Design name */
> +     len = be16_to_cpu(*(uint16_t*)bit);
> +     bit += sizeof(uint16_t);
> +     debug("Design: %s\n", bit);
> +     bit += len;
> +
> +     /* Device identifier */
> +     if (*bit != 'b')
> +             return -1;
> +     bit++;
> +     len = be16_to_cpu(*(uint16_t*)bit);
> +     bit += sizeof(uint16_t);
> +     debug("Device: %s\n", bit);
> +     bit += len;
> +
> +     /* Date */
> +     if (*bit != 'c')
> +             return -1;
> +     bit++;
> +     len = be16_to_cpu(*(uint16_t*)bit);
> +     bit += sizeof(uint16_t);
> +     debug("Date: %s\n", bit);
> +     bit += len;
> +
> +     /* Time */
> +     if (*bit != 'd')
> +             return -1;
> +     bit++;
> +     len = be16_to_cpu(*(uint16_t*)bit);
> +     bit += sizeof(uint16_t);
> +     debug("Time: %s\n", bit);
> +     bit += len;
> +
> +     /* Bitstream length */
> +     if (*bit != 'e')
> +             return -1;
> +     bit++;
> +     bitlen = be32_to_cpu(*(uint32_t*)bit);
> +     bit += sizeof(uint32_t);
> +     bitbin = bit;
> +
> +     debug("Bitstream Length: 0x%x\n", bitlen);
> +     for (i = 0; i < bitlen; i += sizeof(uint32_t)) {
> +             uint32_t *bitbin32 = (uint32_t*)&bitbin[i];
> +             *bitbin32 = __swab32(*bitbin32);
> +     }
> +
> +     if (!bf->dest_dev)
> +             bf->dest_dev = PART_ATTR_DEST_DEVICE_PL;
> +
> +     bf->load = 0xffffffff;
> +     bf->entry = 0;
> +
> +     bf->flags |= 1ULL << BIF_FLAG_BIT_FILE;
> +     return bif_add_part(bf, bit, bitlen);
> +}
> +
> +/* Add .bin bitstream */
> +static int bif_add_bin(struct bif_entry *bf)
> +{
> +     size_t size;
> +     char *bin = read_full_file(bf->filename, &size);
> +
> +     if (!bf->dest_dev)
> +             bf->dest_dev = PART_ATTR_DEST_DEVICE_PS;
> +
> +     bf->flags |= 1ULL << BIF_FLAG_BIN_FILE;
> +     return bif_add_part(bf, bin, size);
> +}
> +
> +/* Add elf file */
> +static char *elf2flat64(char *elf, size_t *flat_size, size_t *load_addr)
> +{
> +     Elf64_Ehdr *ehdr;
> +     Elf64_Shdr *shdr;
> +     size_t min_addr = -1, max_addr = 0;
> +     char *flat;
> +     int i;
> +
> +     ehdr = (void*)elf;
> +     shdr = (void*)(elf + le64_to_cpu(ehdr->e_shoff));
> +
> +     /* Look for smallest / biggest address */
> +     for (i = 0; i < le64_to_cpu(ehdr->e_shnum); i++) {
> +             if (!shdr->sh_size || !shdr->sh_addr ||
> +                 !(shdr->sh_flags & SHF_ALLOC) ||
> +                 (shdr->sh_type == SHT_NOBITS)) {
> +                     shdr++;
> +                     continue;
> +             }
> +
> +             if (le64_to_cpu(shdr->sh_addr) < min_addr)
> +                     min_addr = le64_to_cpu(shdr->sh_addr);
> +             if ((le64_to_cpu(shdr->sh_addr) + le64_to_cpu(shdr->sh_size)) >
> +                     max_addr)
> +                     max_addr = le64_to_cpu(shdr->sh_addr) +
> +                                le64_to_cpu(shdr->sh_size);
> +
> +             shdr++;
> +     }
> +
> +     *load_addr = min_addr;
> +     *flat_size = max_addr - min_addr;
> +     flat = calloc(1, *flat_size);
> +     if (!flat)
> +             return NULL;
> +
> +     shdr = (void*)(elf + le64_to_cpu(ehdr->e_shoff));
> +     for (i = 0; i < le64_to_cpu(ehdr->e_shnum); i++) {
> +             char *dst = flat + le64_to_cpu(shdr->sh_addr) - min_addr;
> +             char *src = elf + le64_to_cpu(shdr->sh_offset);
> +
> +             if (!shdr->sh_size || !shdr->sh_addr ||
> +                 !(shdr->sh_flags & SHF_ALLOC)) {
> +                     shdr++;
> +                     continue;
> +             }
> +
> +             if (shdr->sh_type != SHT_NOBITS) {
> +
> +                     memcpy(dst, src, le64_to_cpu(shdr->sh_size));
> +             }
> +             shdr++;
> +     }
> +
> +     return flat;
> +}
> +
> +static char *elf2flat32(char *elf, size_t *flat_size, size_t *load_addr)
> +{
> +     Elf32_Ehdr *ehdr;
> +     Elf32_Shdr *shdr;
> +     size_t min_addr = -1, max_addr = 0;
> +     char *flat;
> +     int i;
> +
> +     ehdr = (void*)elf;
> +     shdr = (void*)(elf + le32_to_cpu(ehdr->e_shoff));
> +
> +     /* Look for smallest / biggest address */
> +     for (i = 0; i < le32_to_cpu(ehdr->e_shnum); i++) {
> +             if (!shdr->sh_size || !shdr->sh_addr ||
> +                 !(shdr->sh_flags & SHF_ALLOC) ||
> +                 (shdr->sh_type == SHT_NOBITS)) {
> +                     shdr++;
> +                     continue;
> +             }
> +
> +             if (le32_to_cpu(shdr->sh_addr) < min_addr)
> +                     min_addr = le32_to_cpu(shdr->sh_addr);
> +             if ((le32_to_cpu(shdr->sh_addr) + le32_to_cpu(shdr->sh_size)) >
> +                     max_addr)
> +                     max_addr = le32_to_cpu(shdr->sh_addr) +
> +                                le32_to_cpu(shdr->sh_size);
> +
> +             shdr++;
> +     }
> +
> +     *load_addr = min_addr;
> +     *flat_size = max_addr - min_addr;
> +     flat = calloc(1, *flat_size);
> +     if (!flat)
> +             return NULL;
> +
> +     shdr = (void*)(elf + le32_to_cpu(ehdr->e_shoff));
> +     for (i = 0; i < le32_to_cpu(ehdr->e_shnum); i++) {
> +             char *dst = flat + le32_to_cpu(shdr->sh_addr) - min_addr;
> +             char *src = elf + le32_to_cpu(shdr->sh_offset);
> +
> +             if (!shdr->sh_size || !shdr->sh_addr ||
> +                 !(shdr->sh_flags & SHF_ALLOC)) {
> +                     shdr++;
> +                     continue;
> +             }
> +
> +             if (shdr->sh_type != SHT_NOBITS) {
> +
> +                     memcpy(dst, src, le32_to_cpu(shdr->sh_size));
> +             }
> +             shdr++;
> +     }
> +
> +     return flat;
> +}
> +
> +static int bif_add_elf(struct bif_entry *bf)
> +{
> +     size_t size;
> +     size_t elf_size;
> +     char *elf;
> +     char *flat;
> +     size_t load_addr;
> +     Elf32_Ehdr *ehdr32;
> +     Elf64_Ehdr *ehdr64;
> +
> +     elf = read_full_file(bf->filename, &elf_size);
> +     if (!elf)
> +             return -1;
> +
> +     ehdr32 = (void*)elf;
> +     ehdr64 = (void*)elf;
> +
> +     switch (ehdr32->e_ident[EI_CLASS]) {
> +     case ELFCLASS32:
> +             flat = elf2flat32(elf, &size, &load_addr);
> +             bf->entry = le32_to_cpu(ehdr32->e_entry);
> +             break;
> +     case ELFCLASS64:
> +             flat = elf2flat64(elf, &size, &load_addr);
> +             bf->entry = le64_to_cpu(ehdr64->e_entry);
> +             break;
> +     default:
> +             printf("Unknown ELF class: %d\n", ehdr32->e_ident[EI_CLASS]);
> +             return -1;
> +     }
> +
> +     if (!flat)
> +             return -1;
> +
> +     bf->load = load_addr;
> +     if (!bf->dest_dev)
> +             bf->dest_dev = PART_ATTR_DEST_DEVICE_PS;
> +
> +     bf->flags |= 1ULL << BIF_FLAG_ELF_FILE;
> +     return bif_add_part(bf, flat, size);
> +}
> +
> +static const struct bif_file_type bif_file_types[] = {
> +     {
> +             .name = "bitstream (.bit)",
> +             .header = 0x00090ff0,
> +             .add = bif_add_bit,
> +     },
> +
> +     {
> +             .name = "ELF",
> +             .header = 0x7f454c46,
> +             .add = bif_add_elf,
> +     },
> +
> +     /* Anything else is a .bin file */
> +     {
> +             .name = ".bin",
> +             .add = bif_add_bin,
> +     },
> +};
> +
> +static const struct bif_flags *find_flag(char *str)
> +{
> +     const struct bif_flags *bf;
> +     int i;
> +
> +     for (i = 0; i < ARRAY_SIZE(bif_flags); i++) {
> +             bf = &bif_flags[i];
> +             if (!strncmp(bf->name, str, strlen(bf->name)))
> +                     return bf;
> +     }
> +
> +     printf("ERROR: Flag '%s' not found\n", str);
> +
> +     return NULL;
> +}
> +
> +static int bif_open_file(struct bif_entry *entry)
> +{
> +     int fd = open(entry->filename, O_RDONLY);
> +
> +     if (fd < 0)
> +             printf("Error opening file %s\n", entry->filename);
> +
> +     return fd;
> +}
> +
> +static const struct bif_file_type *get_file_type(struct bif_entry *entry)
> +{
> +     int fd = bif_open_file(entry);
> +     uint32_t header;
> +     int i;
> +
> +     if (fd < 0)
> +             return NULL;
> +
> +     if (read(fd, &header, sizeof(header)) != sizeof(header)) {
> +             printf("Error reading file %s", entry->filename);
> +             return NULL;
> +     }
> +
> +     close(fd);
> +
> +     for (i = 0; i < ARRAY_SIZE(bif_file_types); i++) {
> +             const struct bif_file_type *type = &bif_file_types[i];
> +
> +             if (!type->header)
> +                     return type;
> +             if (type->header == be32_to_cpu(header))
> +                     return type;
> +     }
> +
> +     return NULL;
> +}
> +
> +#define NEXT_CHAR(str, chr) ({               \
> +     char *_n = strchr(str, chr);    \
> +     if (!_n)                        \
> +             goto err;               \
> +     _n;                             \
> +})
> +
> +static char *skip_whitespace(char *str)
> +{
> +     while (*str == ' ' || *str == '\t')
> +             str++;
> +
> +     return str;
> +}
> +
> +void zynqmpbif_copy_image(int outfd, struct image_tool_params *mparams)
> +{
> +     char *bif, *bifp, *bifpn;
> +     char *line;
> +     struct bif_entry entries[32] = { { 0 } };
> +     int nr_entries = 0;
> +     struct bif_entry *entry = entries;
> +     size_t len;
> +     int i;
> +     uint32_t csum;
> +
> +     bif_init();
> +
> +     /* Read .bif input file */
> +     bifp = bif = read_full_file(mparams->datafile, NULL);
> +     if (!bif)
> +             goto err;
> +
> +     /* Interpret .bif file */
> +     bifp = bif;
> +
> +     /* A bif description starts with a { section */
> +     bifp = NEXT_CHAR(bifp, '{') + 1;
> +
> +     /* Read every line */
> +     while (1) {
> +             bifpn = NEXT_CHAR(bifp, '\n');
> +
> +             *bifpn = '\0';
> +             bifpn++;
> +             line = bifp;
> +
> +             line = skip_whitespace(line);
> +
> +             /* Attributes? */
> +             if (*line == '[') {
> +                     line++;
> +                     while (1) {
> +                             const struct bif_flags *bf;
> +
> +                             line = skip_whitespace(line);
> +                             bf = find_flag(line);
> +                             if (!bf)
> +                                     goto err;
> +
> +                             line += strlen(bf->name);
> +                             if (bf->parse)
> +                                     line = bf->parse(line, entry);
> +                             else
> +                                     entry->flags |= 1ULL << bf->flag;
> +
> +                             /* Go to next attribute or quit */
> +                             if (*line == ']') {
> +                                     line++;
> +                                     break;
> +                             }
> +                             if (*line == ',')
> +                                     line++;
> +                     }
> +             }
> +
> +             /* End of image description */
> +             if (*line == '}')
> +                     break;
> +
> +             if (*line) {
> +                     line = skip_whitespace(line);
> +                     entry->filename = line;
> +                     nr_entries++;
> +                     entry++;
> +             }
> +
> +             /* Use next line */
> +             bifp = bifpn;
> +     }
> +
> +     for (i = 0; i < nr_entries; i++) {
> +             debug("Entry flags=%#lx name=%s\n", entries[i].flags,
> +                   entries[i].filename);
> +     }
> +
> +     for (i = 0; i < nr_entries; i++) {
> +             struct bif_entry *entry = &entries[i];
> +             const struct bif_file_type *type;
> +             int r;
> +
> +             type = get_file_type(entry);
> +             if (!type)
> +                     goto err;
> +
> +             debug("type=%s file=%s\n", type->name, entry->filename);
> +             r = type->add(entry);
> +             if (r)
> +                     goto err;
> +     }
> +
> +     /* Calculate checksums */
> +     csum = zynqmp_csum(&bif_output.header->width_detection,
> +                        &bif_output.header->checksum);
> +     bif_output.header->checksum = cpu_to_le32(csum);
> +
> +     if (bif_output.imgheader) {
> +             csum = zynqmp_csum(bif_output.imgheader,
> +                                &bif_output.imgheader->checksum);
> +             bif_output.imgheader->checksum = cpu_to_le32(csum);
> +     }
> +
> +     /* Write headers and components */
> +     if (lseek(outfd, 0, SEEK_SET) != 0)
> +             goto err;
> +
> +     len = bif_output.data_len;
> +     bifp = bif_output.data;
> +     while (len) {
> +             int r;
> +             r = write(outfd, bifp, len);
> +             if (r < 0)
> +                     goto err;
> +             len -= r;
> +             bifp += r;
> +     }
> +
> +     return;
> +
> +err:
> +     fprintf(stderr, "Error: Failed to create image.\n");
> +}
> +
> +/* Needs to be stubbed out so we can print after creation */
> +static void zynqmpbif_set_header(void *ptr, struct stat *sbuf, int ifd,
> +             struct image_tool_params *params)
> +{
> +}
> +
> +static struct zynqmp_header zynqmpimage_header;
> +
> +U_BOOT_IMAGE_TYPE(
> +     zynqmpbif,
> +     "Xilinx ZynqMP Boot Image support (bif)",
> +     sizeof(struct zynqmp_header),
> +     (void *)&zynqmpimage_header,
> +     zynqmpbif_check_params,
> +     NULL,
> +     zynqmpimage_print_header,
> +     zynqmpbif_set_header,
> +     NULL,
> +     zynqmpbif_check_image_types,
> +     NULL,
> +     NULL
> +);
> diff --git a/tools/zynqmpimage.c b/tools/zynqmpimage.c
> index 8f4766f077..145391de3e 100644
> --- a/tools/zynqmpimage.c
> +++ b/tools/zynqmpimage.c
> @@ -87,7 +87,7 @@ static uint32_t zynqmpimage_checksum(struct zynqmp_header 
> *ptr)
>       return cpu_to_le32(checksum);
>  }
>  
> -static void zynqmpimage_default_header(struct zynqmp_header *ptr)
> +void zynqmpimage_default_header(struct zynqmp_header *ptr)
>  {
>       int i;
>  
> @@ -211,7 +211,7 @@ static void print_partition(const void *ptr, const struct 
> partition_header *ph)
>       printf("    Checksum   : 0x%08x\n", le32_to_cpu(ph->checksum));
>  }
>  
> -static void zynqmpimage_print_header(const void *ptr)
> +void zynqmpimage_print_header(const void *ptr)
>  {
>       struct zynqmp_header *zynqhdr = (struct zynqmp_header *)ptr;
>       int i;
> diff --git a/tools/zynqmpimage.h b/tools/zynqmpimage.h
> index f3b5c195ad..b421e4f94c 100644
> --- a/tools/zynqmpimage.h
> +++ b/tools/zynqmpimage.h
> @@ -129,4 +129,7 @@ struct zynqmp_header {
>       uint32_t __reserved4[66]; /* 0x9c0 */
>  };
>  
> +void zynqmpimage_default_header(struct zynqmp_header *ptr);
> +void zynqmpimage_print_header(const void *ptr);
> +
>  #endif /* _ZYNQMPIMAGE_H_ */
> 

Also please run checkpatch over it.

Thanks,
Michal

-- 
Michal Simek, Ing. (M.Eng), OpenPGP -> KeyID: FE3D1F91
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel - Xilinx Microblaze
Maintainer of Linux kernel - Xilinx Zynq ARM and ZynqMP ARM64 SoCs
U-Boot custodian - Xilinx Microblaze/Zynq/ZynqMP SoCs

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot

Reply via email to