[Buildroot] [PATCH 1/3] mkpimage: rewrite to support header version 1

Lionel Flandrin lionel at svkt.org
Thu Jan 26 11:25:17 UTC 2017


On Thu, Jan 26, 2017 at 12:16:02PM +0100, Lionel Flandrin wrote:
> mkpimage is a proprietary tool part of Altera's Embedded Development
> Suite which is used to generate the image files supported by their
> BootROMs.
> 
> Newer versions of their SoCs (such as the Arria 10) use header version
> 1 which was not supported by the previous version of this tool.
> 
> This new version supports header version 1, improves error handling
> and tweaks the output to bring it closer to Altera's own tool. In
> particular the padding calculations have been changed. In all the
> configurations tested this program and Altera's mkpimage produce
> exactly the same files (while the previous version didn't).
> 
> Signed-off-by: Lionel Flandrin <lionel at svkt.org>
> ---
>  package/mkpimage/mkpimage.c  | 767 ++++++++++++++++++++++++++++---------------
>  package/mkpimage/mkpimage.mk |   3 -
>  2 files changed, 511 insertions(+), 259 deletions(-)
> 
> diff --git a/package/mkpimage/mkpimage.c b/package/mkpimage/mkpimage.c
> index 1a7a66d98..06e36040c 100644
> --- a/package/mkpimage/mkpimage.c
> +++ b/package/mkpimage/mkpimage.c
> @@ -1,287 +1,542 @@
> +/* Replacement for altera's proprietary mkpimage (part of their EDS)
> + *
> + * Create an Altera BootROM-compatible image of the Second Stage Boot
> + * Loader (SSBL).
> + *
> + * This program should generate the same output as Altera's mkpimage
> + * version 16.1 (build 196). If it doesn't it's a bug.
> + *
> + * The original version of this program was part of barebox.
> + *
> + * Distributed under the GNU GPL v2.
> + */
> +
>  #include <stdio.h>
> -#include <unistd.h>
>  #include <getopt.h>
>  #include <stdlib.h>
>  #include <stdint.h>
>  #include <string.h>
> +#include <unistd.h>
> +#include <fcntl.h>
>  #include <errno.h>
> -#include <sys/types.h>
>  #include <sys/stat.h>
> -#include <fcntl.h>
> -#include <endian.h>
>  
> -#define VALIDATION_WORD 0x31305341
> +#define MKPIMAGE_VERSION "1.0"
>  
> -#define MAX_IMAGE_SIZE (60 * 1024 - 4)
> +#define VALIDATION_WORD 0x31305341
>  
> -static int add_barebox_header;
> +struct socfpga_header_v0 {
> +  uint8_t validation_word[4];
> +  uint8_t version;
> +  uint8_t flags;
> +  uint8_t program_length[2];
> +  uint8_t spare[2];
> +  uint8_t checksum[2];
> +};
>  
> -struct socfpga_header {
> -	uint8_t validation_word[4];
> -	uint8_t version;
> -	uint8_t flags;
> -	uint8_t program_length[2];
> -	uint8_t spare[2];
> -	uint8_t checksum[2];
> +struct socfpga_header_v1 {
> +  uint8_t validation_word[4];
> +  uint8_t version;
> +  uint8_t flags;
> +  uint8_t header_length[2];
> +  uint8_t program_length[4];
> +  uint8_t program_offset[4];
> +  uint8_t spare[2];
> +  uint8_t checksum[2];
>  };
>  
>  static uint32_t bb_header[] = {
> -	0xea00007e,	/* b 0x200  */
> -	0xeafffffe,	/* 1: b 1b  */
> -	0xeafffffe,	/* 1: b 1b  */
> -	0xeafffffe,	/* 1: b 1b  */
> -	0xeafffffe,	/* 1: b 1b  */
> -	0xeafffffe,	/* 1: b 1b  */
> -	0xeafffffe,	/* 1: b 1b  */
> -	0xeafffffe,	/* 1: b 1b  */
> -	0x65726162,	/* 'bare'   */
> -	0x00786f62,	/* 'box\0'  */
> -	0x00000000,	/* padding  */
> -	0x00000000,	/* padding  */
> -	0x00000000,	/* padding  */
> -	0x00000000,	/* padding  */
> -	0x00000000,	/* padding  */
> -	0x00000000,	/* padding  */
> -	0x00000000,	/* socfpga header */
> -	0x00000000,	/* socfpga header */
> -	0x00000000,	/* socfpga header */
> -	0xea00006b,	/* entry. b 0x200  */
> +  0xea00007e,	/* b 0x200  */
> +  0xeafffffe,	/* 1: b 1b  */
> +  0xeafffffe,	/* 1: b 1b  */
> +  0xeafffffe,	/* 1: b 1b  */
> +  0xeafffffe,	/* 1: b 1b  */
> +  0xeafffffe,	/* 1: b 1b  */
> +  0xeafffffe,	/* 1: b 1b  */
> +  0xeafffffe,	/* 1: b 1b  */
> +  0x65726162,	/* 'bare'   */
> +  0x00786f62,	/* 'box\0'  */
> +  0x00000000,	/* padding  */
> +  0x00000000,	/* padding  */
> +  0x00000000,	/* padding  */
> +  0x00000000,	/* padding  */
> +  0x00000000,	/* padding  */
> +  0x00000000,	/* padding  */
> +  0x00000000,	/* socfpga header */
> +  0x00000000,	/* socfpga header */
> +  0x00000000,	/* socfpga header */
> +  0xea00006b,	/* entry. b 0x200  */
>  };
>  
> -static int read_full(int fd, void *buf, size_t size)
> -{
> -	size_t insize = size;
> -	int now;
> -	int total = 0;
> -
> -	while (size) {
> -		now = read(fd, buf, size);
> -		if (now == 0)
> -			return total;
> -		if (now < 0)
> -			return now;
> -		total += now;
> -		size -= now;
> -		buf += now;
> -	}
> -
> -	return insize;
> +static int add_file(int outfd,
> +                    const char *path,
> +                    unsigned header_version,
> +                    size_t alignment,
> +                    int barebox,
> +                    unsigned long entry_offset);
> +static void add_socfpga_header_v0(uint8_t *buf, size_t size);
> +static void add_socfpga_header_v1(uint8_t *buf,
> +                                  size_t size,
> +                                  unsigned long entry_offset);
> +static uint32_t crc32(uint8_t *buf, size_t length);
> +static int write_all(int fd, uint8_t *buf, size_t size);
> +
> +static void usage(const char *bin) {
> +  fprintf(stderr,
> +"Buildroot mkpimage v" MKPIMAGE_VERSION "\n"
> +"\n"
> +"Usage:\n"
> +" Create quad image:\n"
> +"     %1$s [options] -H <num> -o <outfile> <infile> "
> +"<infile> <infile> <infile>\n"
> +" Create single image:\n"
> +"     %1$s [options] -H <num> -o <outfile> <infile>\n"
> +"\n"
> +"Options:\n"
> +"\n"
> +"-h (--help)                  Display this help message and exit\n"
> +"-H (--header-version) <num>  Header version to be created\n"
> +"                             - Arria/Cyclone V = 0\n"
> +"                             - Arria 10        = 1\n"
> +"                             [default: 0]\n"
> +"-a (--alignment) <num>       Address alignment in kilobytes, valid value\n"
> +"                             starts from 64, 128, 256 etc, override if the\n"
> +"                             NAND flash has a larger block size\n"
> +"                             [default: 64 for header v0, 256 for v1]\n"
> +"-o (--output) <outfile>      Output file. Relative and absolute path\n"
> +"                             supported\n"
> +"-b (--barebox)               Add barebox header\n"
> +"-O (--offset) <num>          Program entry offset relative to start of\n"
> +"                             header (0x40). Used for header version 1 only.\n"
> +"                             [default: 20, min: 20]\n", bin);
>  }
>  
> -static int write_full(int fd, void *buf, size_t size)
> -{
> -	size_t insize = size;
> -	int now;
> -
> -	while (size) {
> -		now = write(fd, buf, size);
> -		if (now <= 0)
> -			return now;
> -		size -= now;
> -		buf += now;
> -	}
> -
> -	return insize;
> +
> +int main(int argc, char **argv) {
> +  static struct option opts[] = {
> +    {"help",           no_argument,       NULL, 'h' },
> +    {"header-version", required_argument, NULL, 'H' },
> +    {"alignement",     required_argument, NULL, 'a' },
> +    {"output",         required_argument, NULL, 'o' },
> +    {"barebox",        no_argument,       NULL, 'b' },

Just noticed I forgot "offset" here, I'm going to send a new patch

> +    {NULL,             0,                 NULL,  0  },
> +  };
> +
> +  int opt;
> +  int barebox = 0;
> +  unsigned header_version = 0;
> +  size_t alignment = 0;
> +  int alignment_set = 0;
> +  const char *outfile = NULL;
> +  unsigned nfiles;
> +  unsigned long entry_offset = 20;
> +  int entry_offset_set = 0;
> +  int outfd;
> +  unsigned i;
> +
> +  while ((opt = getopt_long(argc, argv, "hH:a:dfo:bO:", opts, NULL)) != -1) {
> +    switch (opt) {
> +    case 'H':
> +      header_version = optarg[0] - '0';
> +      if (strlen(optarg) != 1 ||
> +          (header_version != 0 && header_version != 1)) {
> +        fprintf(stderr, "Invalid header version: %s\n\n", optarg);
> +        usage(argv[0]);
> +        return EXIT_FAILURE;
> +      }
> +      break;
> +    case 'a':
> +      {
> +        char *endptr;
> +
> +        alignment = strtoul(optarg, &endptr, 0);
> +
> +        if (*endptr != '\0' || alignment == 0) {
> +          fprintf(stderr, "Invalid alignment: %s\n\n", optarg);
> +          usage(argv[0]);
> +          return EXIT_FAILURE;
> +        }
> +
> +        alignment *= 1024;
> +        alignment_set = 1;
> +      }
> +      break;
> +    case 'b':
> +      barebox = 1;
> +      break;
> +    case 'o':
> +      outfile = optarg;
> +      break;
> +    case 'O':
> +      {
> +        char *endptr;
> +
> +        entry_offset = strtoul(optarg, &endptr, 0);
> +
> +        if (*endptr != '\0' || entry_offset < 20) {
> +          fprintf(stderr, "Invalid entry offset: %s\n\n", optarg);
> +          usage(argv[0]);
> +          return EXIT_FAILURE;
> +        }
> +
> +        entry_offset_set = 1;
> +      }
> +      break;
> +    case 'h':
> +    default:
> +      usage(argv[0]);
> +      return EXIT_FAILURE;
> +    }
> +  }
> +
> +  if (outfile == NULL) {
> +    fprintf(stderr, "Missing output file name\n\n");
> +    usage(argv[0]);
> +    return EXIT_FAILURE;
> +  }
> +
> +  if (!alignment_set) {
> +    if (header_version == 0) {
> +      /* Default to 64K */
> +      alignment = 64 * 1024;
> +    } else {
> +      /* V1 defaults to 256K */
> +      alignment = 256 * 1024;
> +    }
> +  }
> +
> +  if (entry_offset_set && header_version == 0) {
> +    fprintf(stderr,
> +            "Error: entry offset is not available in header version 0\n\n");
> +    usage(argv[0]);
> +    return EXIT_FAILURE;
> +  }
> +
> +  nfiles = argc - optind;
> +
> +  if (nfiles != 1 && nfiles != 4) {
> +    fprintf(stderr,
> +            "Wrong number of input files: expected 1 or 4, got %u\n\n",
> +            nfiles);
> +    usage(argv[0]);
> +    return EXIT_FAILURE;
> +  }
> +
> +  outfd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, 0644);
> +  if (outfd == -1) {
> +    fprintf(stderr,
> +            "Couldn't open '%s' for writing: %s\n",
> +            outfile, strerror(errno));
> +    return EXIT_FAILURE;
> +  }
> +
> +  /* Barebox's version of this program doesn't pad the output up to
> +     * alignment, however Altera's mkpimage does. */
> +  if (ftruncate(outfd, alignment * nfiles) == -1) {
> +    fprintf(stderr,
> +            "Couldn't truncate '%s' to %lu: %s\n",
> +            outfile, alignment * nfiles, strerror(errno));
> +    goto unlink;
> +  }
> +
> +  for (i = 0; i < nfiles; i++) {
> +    if (lseek(outfd, i * alignment, SEEK_SET) == -1) {
> +      fprintf(stderr,
> +              "Couldn't seek '%s' to %lu: %s\n",
> +              outfile, i * alignment, strerror(errno));
> +      goto unlink;
> +    }
> +
> +    if (add_file(outfd,
> +                 argv[optind + i],
> +                 header_version,
> +                 alignment,
> +                 barebox,
> +                 entry_offset) == -1) {
> +      goto unlink;
> +    }
> +  }
> +
> +  close(outfd);
> +
> +  return EXIT_SUCCESS;
> +
> + unlink:
> +  /* Something went wrong, delete the output*/
> +  close(outfd);
> +  unlink(outfile);
> +  return EXIT_FAILURE;
>  }
>  
> -static uint32_t crc_table[256] = {
> -	0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
> -	0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
> -	0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7,
> -	0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
> -	0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3,
> -	0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
> -	0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef,
> -	0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
> -	0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb,
> -	0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
> -	0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
> -	0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
> -	0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4,
> -	0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
> -	0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08,
> -	0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
> -	0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc,
> -	0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
> -	0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050,
> -	0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
> -	0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
> -	0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
> -	0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1,
> -	0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
> -	0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5,
> -	0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
> -	0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9,
> -	0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
> -	0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd,
> -	0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
> -	0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
> -	0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
> -	0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2,
> -	0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
> -	0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e,
> -	0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
> -	0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a,
> -	0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
> -	0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676,
> -	0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
> -	0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
> -	0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
> -	0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
> -};
> +static int add_file(int outfd,
> +                    const char *path,
> +                    unsigned header_version,
> +                    size_t alignment,
> +                    int barebox,
> +                    unsigned long entry_offset) {
> +  int fd = -1;
> +  struct stat st;
> +  int ret = -1;
> +  size_t file_size;
> +  size_t out_size;
> +  uint8_t *buffer = NULL;
> +  uint8_t *rbuffer = NULL;
> +  size_t nread = 0;
> +
> +  fd = open(path, O_RDONLY);
> +
> +  if (fd == -1) {
> +     fprintf(stderr, "Couldn't open '%s' for reading: %s\n",
> +             path, strerror(errno));
> +     goto exit;
> +  }
> +
> +  if (fstat(fd, &st) == -1) {
> +    fprintf(stderr,
> +            "Couldn't stat '%s': %s\n",
> +            path, strerror(errno));
> +    goto exit;
> +  }
> +
> +  file_size = st.st_size;
> +
> +  /* Add room for 32bit CRC */
> +  out_size = file_size + sizeof(uint32_t);
> +
> +  if (barebox) {
> +    out_size += 512;
> +  }
> +
> +  /* Barebox's version of this program pads the binary to a multiple
> +   * of 4bytes, however altera's mkpimage pads to 32bytes. I'm not
> +   * sure if it makes a difference in practice but I prefer to be as
> +   * close as possible to the reference.
> +   */
> +  out_size = (out_size + 31UL) & (~31UL);
> +
> +  if (out_size > alignment) {
> +    fprintf(stderr,
> +            "Error: File '%s' is too big to fit the alignment of %luKB\n",
> +            path,
> +            alignment / 1024);
> +      goto exit;
> +  }
> +
> +  buffer = malloc(out_size);
> +  if (buffer == NULL) {
> +    fprintf(stderr, "malloc(%lu) failed\n", out_size);
> +    goto exit;
> +  }
> +
> +  memset(buffer, 0, out_size);
> +
> +  if (barebox) {
> +    memcpy(buffer, bb_header, sizeof(bb_header));
> +    rbuffer = buffer + 512;
> +  } else {
> +    rbuffer = buffer;
> +  }
> +
> +  while (nread < file_size) {
> +    ssize_t n = read(fd, rbuffer + nread, file_size - nread);
> +
> +    if (n < 0) {
> +      fprintf(stderr, "Error while reading '%s': %s\n",
> +              path, strerror(errno));
> +      goto exit;
> +    }
> +
> +    if (n == 0) {
> +      fprintf(stderr, "Error while reading '%s': %s\n",
> +              path, "Short read");
> +      goto exit;
> +    }
> +
> +    nread += (size_t)n;
> +  }
> +
> +  if (header_version == 0) {
> +    add_socfpga_header_v0(buffer, out_size);
> +  } else {
> +    add_socfpga_header_v1(buffer, out_size, entry_offset);
> +  }
> +
> +  if (write_all(outfd, buffer, out_size) == -1) {
> +    goto exit;
> +  }
> +
> +  ret = 0;
> + exit:
> +  if (buffer != NULL) {
> +    free(buffer);
> +  }
> +
> +  if (fd >= 0) {
> +    close(fd);
> +  }
> +
> +  return ret;
> +}
>  
> -uint32_t crc32(uint32_t crc, void *_buf, int length)
> +static void add_socfpga_header_v0(uint8_t *buf, size_t size)
>  {
> -	uint8_t *buf = _buf;
> -
> -	while (length--)
> -		crc = crc << 8 ^ crc_table[(crc >> 24 ^ *(buf++)) & 0xff];
> -
> -	return crc;
> +  struct socfpga_header_v0 *header = (void*)(buf + 0x40);
> +  uint32_t crc;
> +  uint32_t crc_idx;
> +  unsigned checksum;
> +  size_t length = size >> 2;
> +  size_t i;
> +
> +  header->validation_word[0] = VALIDATION_WORD & 0xff;
> +  header->validation_word[1] = (VALIDATION_WORD >> 8) & 0xff;
> +  header->validation_word[2] = (VALIDATION_WORD >> 16) & 0xff;
> +  header->validation_word[3] = (VALIDATION_WORD >> 24) & 0xff;
> +  header->version = 0;
> +  header->flags = 0;
> +  header->program_length[0] = length & 0xff;
> +  header->program_length[1] = (length >> 8) & 0xff;
> +  header->spare[0] = 0;
> +  header->spare[1] = 0;
> +
> +  /* Header checksum */
> +  checksum = 0;
> +  for (i = 0; i < sizeof(*header) - 2; i++)
> +    checksum += buf[i + 0x40];
> +
> +  header->checksum[0] = checksum & 0xff;
> +  header->checksum[1] = (checksum >> 8) & 0xff;
> +
> +  crc = crc32(buf, size - sizeof(uint32_t));
> +
> +  crc_idx = size - sizeof(uint32_t);
> +
> +  buf[crc_idx++] = crc & 0xff;
> +  buf[crc_idx++] = (crc >> 8) & 0xff;
> +  buf[crc_idx++] = (crc >> 16) & 0xff;
> +  buf[crc_idx++] = (crc >> 24) & 0xff;
>  }
>  
> -static int add_socfpga_header(void *buf, int size)
> -{
> -	struct socfpga_header *header = buf + 0x40;
> -	uint8_t *buf_header = buf + 0x40;
> -	uint32_t *crc;
> -	unsigned checksum;
> -	int length = size >> 2;
> -	int i;
> -
> -	if (size & 0x3) {
> -		fprintf(stderr, "%s: size must be multiple of 4\n", __func__);
> -		return -EINVAL;
> -	}
> -
> -	header->validation_word[0] = VALIDATION_WORD & 0xff;
> -	header->validation_word[1] = (VALIDATION_WORD >> 8) & 0xff;
> -	header->validation_word[2] = (VALIDATION_WORD >> 16) & 0xff;
> -	header->validation_word[3] = (VALIDATION_WORD >> 24) & 0xff;
> -	header->version = 0;
> -	header->flags = 0;
> -	header->program_length[0] = length & 0xff;
> -	header->program_length[1] = (length >> 8) & 0xff;
> -	header->spare[0] = 0;
> -	header->spare[1] = 0;
> -
> -	checksum = 0;
> -	for (i = 0; i < sizeof(*header) - 2; i++)
> -		checksum += buf_header[i];
> -
> -	header->checksum[0] = checksum & 0xff;;
> -	header->checksum[1] = (checksum >> 8) & 0xff;;
> -
> -	crc = buf + size - sizeof(uint32_t);
> -
> -	*crc = crc32(0xffffffff, buf, size - sizeof(uint32_t));
> -	*crc ^= 0xffffffff;
> -
> -	return 0;
> +static void add_socfpga_header_v1(uint8_t *buf,
> +                                  size_t size,
> +                                  unsigned long entry_offset) {
> +  struct socfpga_header_v1 *header = (void*)(buf + 0x40);
> +  uint32_t crc;
> +  uint32_t crc_idx;
> +  unsigned checksum;
> +  int i;
> +
> +  header->validation_word[0] = VALIDATION_WORD & 0xff;
> +  header->validation_word[1] = (VALIDATION_WORD >> 8) & 0xff;
> +  header->validation_word[2] = (VALIDATION_WORD >> 16) & 0xff;
> +  header->validation_word[3] = (VALIDATION_WORD >> 24) & 0xff;
> +  header->version = 1;
> +  header->flags = 0;
> +  header->header_length[0] = sizeof(*header) & 0xff;
> +  header->header_length[1] = (sizeof(*header) >> 8) & 0xff;
> +  header->program_length[0] = size & 0xff;
> +  header->program_length[1] = (size >> 8) & 0xff;
> +  header->program_length[2] = (size >> 16) & 0xff;
> +  header->program_length[3] = (size >> 24) & 0xff;
> +  header->program_offset[0] = entry_offset & 0xff;
> +  header->program_offset[1] = (entry_offset >> 8) & 0xff;
> +  header->program_offset[2] = (entry_offset >> 16) & 0xff;
> +  header->program_offset[3] = (entry_offset >> 24) & 0xff;
> +  header->spare[0] = 0;
> +  header->spare[1] = 0;
> +
> +  /* Header checksum */
> +  checksum = 0;
> +  for (i = 0; i < sizeof(*header) - 2; i++)
> +    checksum += buf[i + 0x40];
> +
> +  header->checksum[0] = checksum & 0xff;
> +  header->checksum[1] = (checksum >> 8) & 0xff;
> +
> +  crc = crc32(buf, size - sizeof(uint32_t));
> +
> +  crc_idx = size - sizeof(uint32_t);
> +
> +  buf[crc_idx++] = crc & 0xff;
> +  buf[crc_idx++] = (crc >> 8) & 0xff;
> +  buf[crc_idx++] = (crc >> 16) & 0xff;
> +  buf[crc_idx++] = (crc >> 24) & 0xff;
>  }
>  
> -static void usage(const char *prgname)
> +static int write_all(int fd, uint8_t *buf, size_t size)
>  {
> -	fprintf(stderr, "usage: %s [OPTIONS] <infile>\n", prgname);
> +  while (size) {
> +    ssize_t written = write(fd, buf, size);
> +
> +    if (written < 0) {
> +      fprintf(stderr, "Error while writing: %s\n", strerror(errno));
> +      return -1;
> +    }
> +
> +    if (written == 0) {
> +      fprintf(stderr, "Error while writing: short write\n");
> +      return -1;
> +    }
> +
> +    size -= (size_t)written;
> +    buf += written;
> +  }
> +
> +  return 0;
>  }
>  
> -int main(int argc, char *argv[])
> +static uint32_t crc_table[256] = {
> +  0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
> +  0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
> +  0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7,
> +  0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
> +  0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3,
> +  0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
> +  0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef,
> +  0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
> +  0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb,
> +  0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
> +  0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
> +  0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
> +  0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4,
> +  0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
> +  0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08,
> +  0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
> +  0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc,
> +  0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
> +  0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050,
> +  0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
> +  0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
> +  0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
> +  0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1,
> +  0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
> +  0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5,
> +  0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
> +  0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9,
> +  0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
> +  0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd,
> +  0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
> +  0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
> +  0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
> +  0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2,
> +  0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
> +  0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e,
> +  0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
> +  0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a,
> +  0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
> +  0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676,
> +  0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
> +  0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
> +  0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
> +  0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
> +};
> +
> +uint32_t crc32(uint8_t *buf, size_t length)
>  {
> -	int opt, ret;
> -	const char *outfile = NULL, *infile;
> -	struct stat s;
> -	void *buf;
> -	int fd;
> -	int min_image_size = 80;
> -	int max_image_size = MAX_IMAGE_SIZE;
> -	int addsize = 0, pad;
> -
> -	while ((opt = getopt(argc, argv, "o:hb")) != -1) {
> -		switch (opt) {
> -		case 'b':
> -			add_barebox_header = 1;
> -			min_image_size = 0;
> -			max_image_size = MAX_IMAGE_SIZE - 512;
> -			addsize = 512;
> -			break;
> -		case 'h':
> -			usage(argv[0]);
> -			exit(0);
> -		case 'o':
> -			outfile = optarg;
> -			break;
> -		default:
> -			exit(1);
> -		}
> -	}
> -
> -	if (optind == argc) {
> -		usage(argv[0]);
> -		exit(1);
> -	}
> -
> -	infile = argv[optind];
> -
> -	ret = stat(infile, &s);
> -	if (ret) {
> -		perror("stat");
> -		exit(1);
> -	}
> -
> -	if (s.st_size < min_image_size) {
> -		fprintf(stderr, "input image too small. Minimum is 80 bytes\n");
> -		exit(1);
> -	}
> -
> -	if (s.st_size > max_image_size) {
> -		fprintf(stderr, "input image too big. Maximum is %d bytes, got %ld bytes\n",
> -				max_image_size, s.st_size);
> -		exit(1);
> -	}
> -
> -	fd = open(infile, O_RDONLY);
> -	if (fd < 0) {
> -		perror("open infile");
> -		exit(1);
> -	}
> -
> -	pad = s.st_size & 0x3;
> -	if (pad)
> -		pad = 4 - pad;
> -
> -	buf = calloc(s.st_size + 4 + addsize + pad, 1);
> -	if (!buf) {
> -		perror("malloc");
> -		exit(1);
> -	}
> -
> -	ret = read_full(fd, buf + addsize, s.st_size);
> -	if (ret < 0) {
> -		perror("read infile");
> -		exit(1);
> -	}
> -
> -	close(fd);
> -
> -	if (add_barebox_header) {
> -		memcpy(buf, bb_header, sizeof(bb_header));
> -	}
> -
> -	ret = add_socfpga_header(buf, s.st_size + 4 + addsize + pad);
> -	if (ret)
> -		exit(1);
> -
> -	fd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, 0644);
> -	if (fd < 0) {
> -		perror("open outfile");
> -		exit(1);
> -	}
> -
> -	ret = write_full(fd, buf, s.st_size + 4 + addsize + pad);
> -	if (ret < 0) {
> -		perror("write outfile");
> -		exit(1);
> -	}
> -
> -	exit(0);
> +  uint32_t crc = 0xffffffff;
> +
> +  while (length--) {
> +    crc = crc << 8 ^ crc_table[(crc >> 24 ^ *(buf++)) & 0xff];
> +  }
> +
> +  return crc ^ 0xffffffff;
>  }
> diff --git a/package/mkpimage/mkpimage.mk b/package/mkpimage/mkpimage.mk
> index c30a6809c..0236062b6 100644
> --- a/package/mkpimage/mkpimage.mk
> +++ b/package/mkpimage/mkpimage.mk
> @@ -4,9 +4,6 @@
>  #
>  ################################################################################
>  
> -# source included in the package
> -# came from barebox's repository:
> -# http://git.pengutronix.de/?p=barebox.git;a=blob;f=scripts/socfpga_mkimage.c;h=1a7a66d98841e9f52c3ea49c651286aa1412c9a5;hb=HEAD
>  HOST_MKPIMAGE_LICENSE = GPLv2
>  
>  define HOST_MKPIMAGE_BUILD_CMDS
> -- 
> 2.11.0
> 

-- 
Lionel Flandrin
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://lists.busybox.net/pipermail/buildroot/attachments/20170126/c0b1957d/attachment.asc>


More information about the buildroot mailing list