All of lore.kernel.org
 help / color / mirror / Atom feed
* [Buildroot] [PATCH 1/3] mkpimage: rewrite to support header version 1
@ 2017-01-26 11:16 Lionel Flandrin
  2017-01-26 11:17 ` [Buildroot] [PATCH 2/3] u-boot: Add support for Altera mkpimage generation Lionel Flandrin
  2017-01-26 11:25 ` [Buildroot] [PATCH 1/3] mkpimage: rewrite to support header version 1 Lionel Flandrin
  0 siblings, 2 replies; 24+ messages in thread
From: Lionel Flandrin @ 2017-01-26 11:16 UTC (permalink / raw)
  To: buildroot

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@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' },
+    {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

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [Buildroot] [PATCH 2/3] u-boot: Add support for Altera mkpimage generation
  2017-01-26 11:16 [Buildroot] [PATCH 1/3] mkpimage: rewrite to support header version 1 Lionel Flandrin
@ 2017-01-26 11:17 ` Lionel Flandrin
  2017-01-26 11:17   ` [Buildroot] [PATCH 3/3] DEVELOPERS: Add Lionel Flandrin to package/mkpimage Lionel Flandrin
  2017-01-26 11:25 ` [Buildroot] [PATCH 1/3] mkpimage: rewrite to support header version 1 Lionel Flandrin
  1 sibling, 1 reply; 24+ messages in thread
From: Lionel Flandrin @ 2017-01-26 11:17 UTC (permalink / raw)
  To: buildroot

This image format is used by Altera's SoC FPGAs BootROMs.

Signed-off-by: Lionel Flandrin <lionel@svkt.org>
---
 boot/uboot/Config.in | 30 ++++++++++++++++++++++++++++++
 boot/uboot/uboot.mk  | 12 ++++++++++++
 2 files changed, 42 insertions(+)

diff --git a/boot/uboot/Config.in b/boot/uboot/Config.in
index 4e629c0ef..30db8d8b4 100644
--- a/boot/uboot/Config.in
+++ b/boot/uboot/Config.in
@@ -255,6 +255,36 @@ config BR2_TARGET_UBOOT_FORMAT_NAND_ERASE_SIZE
 
 endif
 
+config BR2_TARGET_UBOOT_FORMAT_MKPIMAGE
+       bool "u-boot-dtb.mkpimage (Altera SoC BootROMs)"
+       help
+          Altera's mkpimage format used on their SoCs.
+
+if BR2_TARGET_UBOOT_FORMAT_MKPIMAGE
+
+choice
+       prompt "mkpimage header"
+       default BR2_TARGET_UBOOT_FORMAT_MKPIMAGE_V1
+       help
+         Select the header format for mkpimage
+
+config BR2_TARGET_UBOOT_FORMAT_MKPIMAGE_V0
+       bool "Arria/Cyclone V (v0)"
+       help
+         Header version 1, used by the Arria V and Cyclone V SoCs
+
+config BR2_TARGET_UBOOT_FORMAT_MKPIMAGE_V1
+       bool "Arria 10 (v1)"
+       help
+         Header version 1, used by the Arria10 SoC
+endchoice
+
+config BR2_TARGET_UBOOT_FORMAT_MKPIMAGE_VERSION
+       int
+       default 0 if BR2_TARGET_UBOOT_FORMAT_MKPIMAGE_V0
+       default 1 if BR2_TARGET_UBOOT_FORMAT_MKPIMAGE_V1
+endif
+
 config BR2_TARGET_UBOOT_FORMAT_CUSTOM
 	bool "Custom (specify below)"
 	help
diff --git a/boot/uboot/uboot.mk b/boot/uboot/uboot.mk
index 6b9d54454..d48521a26 100644
--- a/boot/uboot/uboot.mk
+++ b/boot/uboot/uboot.mk
@@ -104,6 +104,18 @@ UBOOT_MAKE_TARGET += u-boot.sb
 UBOOT_DEPENDENCIES += host-elftosb host-openssl
 endif
 
+ifeq ($(BR2_TARGET_UBOOT_FORMAT_MKPIMAGE),y)
+define UBOOT_ALTERA_MKPIMAGE
+       $(HOST_DIR)/usr/bin/mkpimage \
+               --header-version $(BR2_TARGET_UBOOT_FORMAT_MKPIMAGE_VERSION) \
+               -o $(BINARIES_DIR)/u-boot-dtb.mkpimage \
+               $(@D)/u-boot-dtb.bin
+endef
+UBOOT_MAKE_TARGET += u-boot-dtb.bin
+UBOOT_DEPENDENCIES += host-mkpimage
+UBOOT_POST_INSTALL_IMAGES_HOOKS += UBOOT_ALTERA_MKPIMAGE
+endif
+
 ifeq ($(BR2_TARGET_UBOOT_FORMAT_CUSTOM),y)
 UBOOT_BINS += $(call qstrip,$(BR2_TARGET_UBOOT_FORMAT_CUSTOM_NAME))
 endif
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [Buildroot] [PATCH 3/3] DEVELOPERS: Add Lionel Flandrin to package/mkpimage
  2017-01-26 11:17 ` [Buildroot] [PATCH 2/3] u-boot: Add support for Altera mkpimage generation Lionel Flandrin
@ 2017-01-26 11:17   ` Lionel Flandrin
  0 siblings, 0 replies; 24+ messages in thread
From: Lionel Flandrin @ 2017-01-26 11:17 UTC (permalink / raw)
  To: buildroot

Signed-off-by: Lionel Flandrin <lionel@svkt.org>
---
 DEVELOPERS | 1 +
 1 file changed, 1 insertion(+)

diff --git a/DEVELOPERS b/DEVELOPERS
index cd0e66480..44be22787 100644
--- a/DEVELOPERS
+++ b/DEVELOPERS
@@ -918,6 +918,7 @@ N:	Lee Jones <lee.jones@linaro.org>
 F:	boot/afboot-stm32/
 
 N:	Lionel Flandrin <lionel@svkt.org>
+F:	package/mkpimage/
 F:	package/python-babel/
 F:	package/python-flask-babel/
 
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [Buildroot] [PATCH 1/3] mkpimage: rewrite to support header version 1
  2017-01-26 11:16 [Buildroot] [PATCH 1/3] mkpimage: rewrite to support header version 1 Lionel Flandrin
  2017-01-26 11:17 ` [Buildroot] [PATCH 2/3] u-boot: Add support for Altera mkpimage generation Lionel Flandrin
@ 2017-01-26 11:25 ` Lionel Flandrin
  2017-01-26 11:28   ` Lionel Flandrin
  1 sibling, 1 reply; 24+ messages in thread
From: Lionel Flandrin @ 2017-01-26 11:25 UTC (permalink / raw)
  To: buildroot

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@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>

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [Buildroot] [PATCH 1/3] mkpimage: rewrite to support header version 1
  2017-01-26 11:25 ` [Buildroot] [PATCH 1/3] mkpimage: rewrite to support header version 1 Lionel Flandrin
@ 2017-01-26 11:28   ` Lionel Flandrin
  2017-01-27  8:17     ` Thomas Petazzoni
  0 siblings, 1 reply; 24+ messages in thread
From: Lionel Flandrin @ 2017-01-26 11:28 UTC (permalink / raw)
  To: buildroot

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@svkt.org>
---
 package/mkpimage/mkpimage.c  | 768 ++++++++++++++++++++++++++++---------------
 package/mkpimage/mkpimage.mk |   3 -
 2 files changed, 512 insertions(+), 259 deletions(-)

diff --git a/package/mkpimage/mkpimage.c b/package/mkpimage/mkpimage.c
index 1a7a66d98..7859ae398 100644
--- a/package/mkpimage/mkpimage.c
+++ b/package/mkpimage/mkpimage.c
@@ -1,287 +1,543 @@
+/* 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' },
+    {"offset",         required_argument, NULL, 'O' },
+    {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

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [Buildroot] [PATCH 1/3] mkpimage: rewrite to support header version 1
  2017-01-26 11:28   ` Lionel Flandrin
@ 2017-01-27  8:17     ` Thomas Petazzoni
  2017-01-27  9:52       ` Lionel Flandrin
  0 siblings, 1 reply; 24+ messages in thread
From: Thomas Petazzoni @ 2017-01-27  8:17 UTC (permalink / raw)
  To: buildroot

Hello,

On Thu, 26 Jan 2017 12:28:31 +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@svkt.org>

Why not import the new version of this program available in Barebox,
which does support V1 headers nowadays?

Otherwise, where does your version comes from?

Best regards,

Thomas
-- 
Thomas Petazzoni, CTO, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [Buildroot] [PATCH 1/3] mkpimage: rewrite to support header version 1
  2017-01-27  8:17     ` Thomas Petazzoni
@ 2017-01-27  9:52       ` Lionel Flandrin
  2017-01-28  8:42         ` Thomas Petazzoni
  0 siblings, 1 reply; 24+ messages in thread
From: Lionel Flandrin @ 2017-01-27  9:52 UTC (permalink / raw)
  To: buildroot

On Fri, Jan 27, 2017 at 09:17:03PM +1300, Thomas Petazzoni wrote:
> Hello,
> 
> On Thu, 26 Jan 2017 12:28:31 +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@svkt.org>
> 
> Why not import the new version of this program available in Barebox,
> which does support V1 headers nowadays?

Because I only noticed that too late... The comment about the barebox
version was in the mk and when I saw it I was almost already done with
my version. My search engine skills failed me once again.

Furthermore this version supports some additional parameters like
setting the alignment and the entry point offset in the header (which
are also supported in Altera's tool). It's also a little more user
friendly (better error reporting etc...). Not a huge deal but still.

More importantly it's closer to Altera's original mkpimage, both in
command line usage and in the resulting image format making it a
better canditate for drop-in replacement. So I decided that it was
worth finishing it.

> Otherwise, where does your version comes from?

It's original work based on the current version of mkpimage.c in the
buildroot repo and my reverse-engineering of version 16.1 of Altera's
closed source java-based mkpimage.

I realize it might make it a bit "off-topic" for inclusion in source
form in buildroot's repo but it's not exactly complicated code either,
it's a simple 14byte header and a 32bit CRC.

I've compared the output of this code with altera's and barebox's
version and they all generate the same binaries with the caveat that
barebox's version uses different alignment constraints and doesn't
handle certain options.

But really it's up to you, for my current use case I can live with
barebox's updated version if you prefer. Alternatively I could try
getting this version of the code in barebox first, even though I don't
use the project myself.

> Best regards,
> 
> Thomas

Thank you for taking the time to review this,
-- 
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/20170127/ae7fd5f0/attachment.asc>

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [Buildroot] [PATCH 1/3] mkpimage: rewrite to support header version 1
  2017-01-27  9:52       ` Lionel Flandrin
@ 2017-01-28  8:42         ` Thomas Petazzoni
  2017-01-28 11:27           ` Lionel Flandrin
  0 siblings, 1 reply; 24+ messages in thread
From: Thomas Petazzoni @ 2017-01-28  8:42 UTC (permalink / raw)
  To: buildroot

Hello,

On Fri, 27 Jan 2017 10:52:51 +0100, Lionel Flandrin wrote:

> But really it's up to you, for my current use case I can live with
> barebox's updated version if you prefer. Alternatively I could try
> getting this version of the code in barebox first, even though I don't
> use the project myself.

If the Barebox version works for you, then I'd prefer if we could stick
to it.

Thomas
-- 
Thomas Petazzoni, CTO, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [Buildroot] [PATCH 1/3] mkpimage: rewrite to support header version 1
  2017-01-28  8:42         ` Thomas Petazzoni
@ 2017-01-28 11:27           ` Lionel Flandrin
  2017-01-30 10:33             ` [Buildroot] [PATCH 1/2] mkpimage: bump to latest barebox version Lionel Flandrin
  0 siblings, 1 reply; 24+ messages in thread
From: Lionel Flandrin @ 2017-01-28 11:27 UTC (permalink / raw)
  To: buildroot

On Sat, Jan 28, 2017 at 09:42:28PM +1300, Thomas Petazzoni wrote:
> Hello,
> 
> On Fri, 27 Jan 2017 10:52:51 +0100, Lionel Flandrin wrote:
> 
> > But really it's up to you, for my current use case I can live with
> > barebox's updated version if you prefer. Alternatively I could try
> > getting this version of the code in barebox first, even though I don't
> > use the project myself.
> 
> If the Barebox version works for you, then I'd prefer if we could stick
> to it.

Fair enough, I'll submit an other patch.

> 
> Thomas
> -- 
> Thomas Petazzoni, CTO, Free Electrons
> Embedded Linux and Kernel engineering
> http://free-electrons.com

-- 
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/20170128/7fd20d0d/attachment.asc>

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [Buildroot] [PATCH 1/2] mkpimage: bump to latest barebox version
  2017-01-28 11:27           ` Lionel Flandrin
@ 2017-01-30 10:33             ` Lionel Flandrin
  2017-01-30 10:33               ` [Buildroot] [PATCH 2/2] u-boot: Add support for Altera mkpimage generation Lionel Flandrin
  2017-02-09 22:34               ` [Buildroot] [PATCH 1/2] mkpimage: bump to latest barebox version Thomas Petazzoni
  0 siblings, 2 replies; 24+ messages in thread
From: Lionel Flandrin @ 2017-01-30 10:33 UTC (permalink / raw)
  To: buildroot

Adds support for header v1 (used on Arria 10 SoCs)

Signed-off-by: Lionel Flandrin <lionel@svkt.org>
---
 package/mkpimage/mkpimage.c  | 149 ++++++++++++++++++++++++++++++++++---------
 package/mkpimage/mkpimage.mk |   6 +-
 2 files changed, 122 insertions(+), 33 deletions(-)

diff --git a/package/mkpimage/mkpimage.c b/package/mkpimage/mkpimage.c
index 1a7a66d98..d7fe1b1b6 100644
--- a/package/mkpimage/mkpimage.c
+++ b/package/mkpimage/mkpimage.c
@@ -12,7 +12,12 @@
 
 #define VALIDATION_WORD 0x31305341
 
-#define MAX_IMAGE_SIZE (60 * 1024 - 4)
+#define BRANCH_INST 0xea /* ARM opcode for "b" (unconditional branch) */
+
+#define MAX_V0IMAGE_SIZE (60 * 1024 - 4)
+/* Max size without authentication is 224 KB, due to memory used by
+ * the ROM boot code as a workspace out of the 256 KB of OCRAM */
+#define MAX_V1IMAGE_SIZE (224 * 1024 - 4)
 
 static int add_barebox_header;
 
@@ -20,9 +25,21 @@ 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];
+	union {
+		struct {
+			uint8_t program_length[2];
+			uint8_t spare[2];
+			uint8_t checksum[2];
+			uint8_t start_vector[4];
+		} v0;
+		struct {
+			uint8_t header_length[2];
+			uint8_t program_length[4];
+			uint8_t entry_offset[4];
+			uint8_t spare[2];
+			uint8_t checksum[2];
+		} v1;
+	};
 };
 
 static uint32_t bb_header[] = {
@@ -45,7 +62,7 @@ static uint32_t bb_header[] = {
 	0x00000000,	/* socfpga header */
 	0x00000000,	/* socfpga header */
 	0x00000000,	/* socfpga header */
-	0xea00006b,	/* entry. b 0x200  */
+	0xea00006b,	/* entry. b 0x200 (offset may be adjusted) */
 };
 
 static int read_full(int fd, void *buf, size_t size)
@@ -84,7 +101,7 @@ static int write_full(int fd, void *buf, size_t size)
 	return insize;
 }
 
-static uint32_t crc_table[256] = {
+static const uint32_t crc_table[256] = {
 	0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
 	0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
 	0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7,
@@ -140,37 +157,94 @@ uint32_t crc32(uint32_t crc, void *_buf, int length)
 	return crc;
 }
 
-static int add_socfpga_header(void *buf, int size)
+/* Create an ARM relative branch instuction 
+ * branch is where the instruction will be placed and dest points to where
+ * it should branch too. */
+static void branch(uint8_t *branch, uint8_t *dest)
+{
+	int offset = dest - branch - 8; /* PC is offset +8 bytes on ARM */
+
+	branch[0] = (offset >> 2) & 0xff; /* instruction uses offset/4 */
+	branch[1] = (offset >> 10) & 0xff;
+	branch[2] = (offset >> 18) & 0xff;
+	branch[3] = BRANCH_INST;
+}
+
+/* start_addr is where the socfpga header's start instruction should branch to.
+ * It should be relative to the start of buf */
+static int add_socfpga_header(void *buf, size_t size, unsigned start_addr, unsigned version)
 {
 	struct socfpga_header *header = buf + 0x40;
-	uint8_t *buf_header = buf + 0x40;
+	void *entry;
+	uint8_t *bufp, *sumendp;
 	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;
 	}
 
+	/* Absolute address of entry point in buf */
+	entry = buf + start_addr;
+	if (version == 0) {
+		sumendp = &header->v0.checksum[0];
+	} else {
+		sumendp = &header->v1.checksum[0];
+
+		/* The ROM loader can't handle a negative offset */
+		if (entry < (void*)header) {
+			/* add a trampoline branch inst after end of the header */
+			uint8_t *trampoline = (void*)(header + 1);
+			branch(trampoline, entry);
+
+			/* and then make the trampoline the entry point */
+			entry = trampoline;
+		}
+		/* Calculate start address as offset relative to start of header */
+		start_addr = entry - (void*)header;
+	}
+
 	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->version = version;
 	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];
+	if (version == 0) {
+		header->v0.program_length[0] = (size >>  2) & 0xff; /* length in words */
+		header->v0.program_length[1] = (size >> 10) & 0xff;
+		header->v0.spare[0] = 0;
+		header->v0.spare[1] = 0;
+		branch(header->v0.start_vector, entry);
+	} else {
+		header->v1.header_length[0] = (sizeof(*header) >> 0) & 0xff;
+		header->v1.header_length[1] = (sizeof(*header) >> 8) & 0xff;
+		header->v1.program_length[0] = (size >>  0) & 0xff;
+		header->v1.program_length[1] = (size >>  8) & 0xff;
+		header->v1.program_length[2] = (size >> 16) & 0xff;
+		header->v1.program_length[3] = (size >> 24) & 0xff;
+		header->v1.entry_offset[0] = (start_addr >>  0) & 0xff;
+		header->v1.entry_offset[1] = (start_addr >>  8) & 0xff;
+		header->v1.entry_offset[2] = (start_addr >> 16) & 0xff;
+		header->v1.entry_offset[3] = (start_addr >> 24) & 0xff;
+		header->v1.spare[0] = 0;
+		header->v1.spare[1] = 0;
+	}
 
-	header->checksum[0] = checksum & 0xff;;
-	header->checksum[1] = (checksum >> 8) & 0xff;;
+	/* Sum from beginning of header to start of checksum field */
+	checksum = 0;
+	for (bufp = (uint8_t*)header; bufp < sumendp; bufp++)
+		checksum += *bufp;
+
+	if (version == 0) {
+		header->v0.checksum[0] = checksum & 0xff;;
+		header->v0.checksum[1] = (checksum >> 8) & 0xff;;
+	} else {
+		header->v1.checksum[0] = checksum & 0xff;;
+		header->v1.checksum[1] = (checksum >> 8) & 0xff;;
+	}
 
 	crc = buf + size - sizeof(uint32_t);
 
@@ -182,7 +256,7 @@ static int add_socfpga_header(void *buf, int size)
 
 static void usage(const char *prgname)
 {
-	fprintf(stderr, "usage: %s [OPTIONS] <infile>\n", prgname);
+	fprintf(stderr, "usage: %s [-hb] [-v version] <infile> -o <outfile>\n", prgname);
 }
 
 int main(int argc, char *argv[])
@@ -192,16 +266,23 @@ int main(int argc, char *argv[])
 	struct stat s;
 	void *buf;
 	int fd;
-	int min_image_size = 80;
-	int max_image_size = MAX_IMAGE_SIZE;
+	int max_image_size, min_image_size = 80;
 	int addsize = 0, pad;
+	unsigned int version = 0;
 
-	while ((opt = getopt(argc, argv, "o:hb")) != -1) {
+	while ((opt = getopt(argc, argv, "o:hbv:")) != -1) {
 		switch (opt) {
+		case 'v':
+			version = atoi(optarg);
+			if (version > 1) {
+				printf("Versions supported: 0 or 1\n");
+				usage(argv[0]);
+				exit(1);
+			}
+			break;
 		case 'b':
 			add_barebox_header = 1;
 			min_image_size = 0;
-			max_image_size = MAX_IMAGE_SIZE - 512;
 			addsize = 512;
 			break;
 		case 'h':
@@ -211,15 +292,21 @@ int main(int argc, char *argv[])
 			outfile = optarg;
 			break;
 		default:
+			usage(argv[0]);
 			exit(1);
 		}
 	}
+	if (version == 0) {
+		max_image_size = MAX_V0IMAGE_SIZE;
+	} else {
+		max_image_size = MAX_V1IMAGE_SIZE;
+	}
+	max_image_size -= addsize;
 
-	if (optind == argc) {
+	if (optind == argc || !outfile) {
 		usage(argv[0]);
 		exit(1);
 	}
-
 	infile = argv[optind];
 
 	ret = stat(infile, &s);
@@ -229,7 +316,8 @@ int main(int argc, char *argv[])
 	}
 
 	if (s.st_size < min_image_size) {
-		fprintf(stderr, "input image too small. Minimum is 80 bytes\n");
+		fprintf(stderr, "input image too small. Minimum is %d bytes\n",
+			min_image_size);
 		exit(1);
 	}
 
@@ -240,7 +328,7 @@ int main(int argc, char *argv[])
 	}
 
 	fd = open(infile, O_RDONLY);
-	if (fd < 0) {
+	if (fd == -1) {
 		perror("open infile");
 		exit(1);
 	}
@@ -267,7 +355,8 @@ int main(int argc, char *argv[])
 		memcpy(buf, bb_header, sizeof(bb_header));
 	}
 
-	ret = add_socfpga_header(buf, s.st_size + 4 + addsize + pad);
+	ret = add_socfpga_header(buf, s.st_size + 4 + addsize + pad, addsize,
+	                         version);
 	if (ret)
 		exit(1);
 
diff --git a/package/mkpimage/mkpimage.mk b/package/mkpimage/mkpimage.mk
index c30a6809c..04b2ef080 100644
--- a/package/mkpimage/mkpimage.mk
+++ b/package/mkpimage/mkpimage.mk
@@ -4,11 +4,11 @@
 #
 ################################################################################
 
-# 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
 
+# source included in the package
+# came from barebox's repository:
+# https://git.pengutronix.de/cgit/barebox/tree/scripts/socfpga_mkimage.c?id=55d29525146dcd280987dfd565bfd34f08858fb3
 define HOST_MKPIMAGE_BUILD_CMDS
 	$(HOSTCC) $(HOST_CFLAGS) $(HOST_LDFLAGS) \
 		package/mkpimage/mkpimage.c -o $(@D)/mkpimage
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [Buildroot] [PATCH 2/2] u-boot: Add support for Altera mkpimage generation
  2017-01-30 10:33             ` [Buildroot] [PATCH 1/2] mkpimage: bump to latest barebox version Lionel Flandrin
@ 2017-01-30 10:33               ` Lionel Flandrin
  2017-02-09 22:33                 ` Thomas Petazzoni
  2017-02-13 13:59                 ` [Buildroot] [PATCH 1/2] u-boot: add an option to generate u-boot-dtb.bin Lionel Flandrin
  2017-02-09 22:34               ` [Buildroot] [PATCH 1/2] mkpimage: bump to latest barebox version Thomas Petazzoni
  1 sibling, 2 replies; 24+ messages in thread
From: Lionel Flandrin @ 2017-01-30 10:33 UTC (permalink / raw)
  To: buildroot

This image format is used by Altera's SoC FPGAs BootROMs.

Signed-off-by: Lionel Flandrin <lionel@svkt.org>
---
 boot/uboot/Config.in | 30 ++++++++++++++++++++++++++++++
 boot/uboot/uboot.mk  | 12 ++++++++++++
 2 files changed, 42 insertions(+)

diff --git a/boot/uboot/Config.in b/boot/uboot/Config.in
index 4e629c0ef..30db8d8b4 100644
--- a/boot/uboot/Config.in
+++ b/boot/uboot/Config.in
@@ -255,6 +255,36 @@ config BR2_TARGET_UBOOT_FORMAT_NAND_ERASE_SIZE
 
 endif
 
+config BR2_TARGET_UBOOT_FORMAT_MKPIMAGE
+       bool "u-boot-dtb.mkpimage (Altera SoC BootROMs)"
+       help
+          Altera's mkpimage format used on their SoCs.
+
+if BR2_TARGET_UBOOT_FORMAT_MKPIMAGE
+
+choice
+       prompt "mkpimage header"
+       default BR2_TARGET_UBOOT_FORMAT_MKPIMAGE_V1
+       help
+         Select the header format for mkpimage
+
+config BR2_TARGET_UBOOT_FORMAT_MKPIMAGE_V0
+       bool "Arria/Cyclone V (v0)"
+       help
+         Header version 1, used by the Arria V and Cyclone V SoCs
+
+config BR2_TARGET_UBOOT_FORMAT_MKPIMAGE_V1
+       bool "Arria 10 (v1)"
+       help
+         Header version 1, used by the Arria10 SoC
+endchoice
+
+config BR2_TARGET_UBOOT_FORMAT_MKPIMAGE_VERSION
+       int
+       default 0 if BR2_TARGET_UBOOT_FORMAT_MKPIMAGE_V0
+       default 1 if BR2_TARGET_UBOOT_FORMAT_MKPIMAGE_V1
+endif
+
 config BR2_TARGET_UBOOT_FORMAT_CUSTOM
 	bool "Custom (specify below)"
 	help
diff --git a/boot/uboot/uboot.mk b/boot/uboot/uboot.mk
index 6b9d54454..7637349fa 100644
--- a/boot/uboot/uboot.mk
+++ b/boot/uboot/uboot.mk
@@ -104,6 +104,18 @@ UBOOT_MAKE_TARGET += u-boot.sb
 UBOOT_DEPENDENCIES += host-elftosb host-openssl
 endif
 
+ifeq ($(BR2_TARGET_UBOOT_FORMAT_MKPIMAGE),y)
+define UBOOT_ALTERA_MKPIMAGE
+       $(HOST_DIR)/usr/bin/mkpimage \
+               -v $(BR2_TARGET_UBOOT_FORMAT_MKPIMAGE_VERSION) \
+               -o $(BINARIES_DIR)/u-boot-dtb.mkpimage \
+               $(@D)/u-boot-dtb.bin
+endef
+UBOOT_MAKE_TARGET += u-boot-dtb.bin
+UBOOT_DEPENDENCIES += host-mkpimage
+UBOOT_POST_INSTALL_IMAGES_HOOKS += UBOOT_ALTERA_MKPIMAGE
+endif
+
 ifeq ($(BR2_TARGET_UBOOT_FORMAT_CUSTOM),y)
 UBOOT_BINS += $(call qstrip,$(BR2_TARGET_UBOOT_FORMAT_CUSTOM_NAME))
 endif
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [Buildroot] [PATCH 2/2] u-boot: Add support for Altera mkpimage generation
  2017-01-30 10:33               ` [Buildroot] [PATCH 2/2] u-boot: Add support for Altera mkpimage generation Lionel Flandrin
@ 2017-02-09 22:33                 ` Thomas Petazzoni
  2017-02-10  9:10                   ` Lionel Flandrin
  2017-02-13 13:59                 ` [Buildroot] [PATCH 1/2] u-boot: add an option to generate u-boot-dtb.bin Lionel Flandrin
  1 sibling, 1 reply; 24+ messages in thread
From: Thomas Petazzoni @ 2017-02-09 22:33 UTC (permalink / raw)
  To: buildroot

Hello,

On Mon, 30 Jan 2017 11:33:26 +0100, Lionel Flandrin wrote:
> This image format is used by Altera's SoC FPGAs BootROMs.
> 
> Signed-off-by: Lionel Flandrin <lionel@svkt.org>

I missed it on my first review, but it seems like you missed it as
well: we already have some logic in uboot.mk to call mkpimage. See the
BR2_TARGET_UBOOT_ALTERA_SOCFPGA_IMAGE_CRC option.

This should be extended rather than having two options doing the same
thing.

Thanks!

Thomas
-- 
Thomas Petazzoni, CTO, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [Buildroot] [PATCH 1/2] mkpimage: bump to latest barebox version
  2017-01-30 10:33             ` [Buildroot] [PATCH 1/2] mkpimage: bump to latest barebox version Lionel Flandrin
  2017-01-30 10:33               ` [Buildroot] [PATCH 2/2] u-boot: Add support for Altera mkpimage generation Lionel Flandrin
@ 2017-02-09 22:34               ` Thomas Petazzoni
  1 sibling, 0 replies; 24+ messages in thread
From: Thomas Petazzoni @ 2017-02-09 22:34 UTC (permalink / raw)
  To: buildroot

Hello,

On Mon, 30 Jan 2017 11:33:25 +0100, Lionel Flandrin wrote:
> Adds support for header v1 (used on Arria 10 SoCs)
> 
> Signed-off-by: Lionel Flandrin <lionel@svkt.org>
> ---
>  package/mkpimage/mkpimage.c  | 149 ++++++++++++++++++++++++++++++++++---------
>  package/mkpimage/mkpimage.mk |   6 +-
>  2 files changed, 122 insertions(+), 33 deletions(-)

Applied to master, thanks.

Thomas
-- 
Thomas Petazzoni, CTO, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [Buildroot] [PATCH 2/2] u-boot: Add support for Altera mkpimage generation
  2017-02-09 22:33                 ` Thomas Petazzoni
@ 2017-02-10  9:10                   ` Lionel Flandrin
  2017-02-10  9:30                     ` Thomas Petazzoni
  0 siblings, 1 reply; 24+ messages in thread
From: Lionel Flandrin @ 2017-02-10  9:10 UTC (permalink / raw)
  To: buildroot

On Thu, Feb 09, 2017 at 11:33:23PM +0100, Thomas Petazzoni wrote:
> Hello,
> 
> On Mon, 30 Jan 2017 11:33:26 +0100, Lionel Flandrin wrote:
> > This image format is used by Altera's SoC FPGAs BootROMs.
> > 
> > Signed-off-by: Lionel Flandrin <lionel@svkt.org>
> 
> I missed it on my first review, but it seems like you missed it as
> well: we already have some logic in uboot.mk to call mkpimage. See the
> BR2_TARGET_UBOOT_ALTERA_SOCFPGA_IMAGE_CRC option.
> 
> This should be extended rather than having two options doing the same
> thing.

I didn't miss it but the existing code is used for u-boot SPL
generation, I didn't think there was an easy way to reuse it for
"full" u-boot packaging (but admitedly my Make-foo is a bit
weak). It's a different set of options.

The previous altera chips only had a 64K internal RAM which meant that
you almost always had to use a SPL to bootstrap the bootloader. The
newer chips however contain 256K of internal RAM so you can fit a full
u-boot in a single stage quite snugly.

> Thanks!
> 
> Thomas

Thank you for reviewing this,
-- 
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/20170210/7b5e1554/attachment.asc>

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [Buildroot] [PATCH 2/2] u-boot: Add support for Altera mkpimage generation
  2017-02-10  9:10                   ` Lionel Flandrin
@ 2017-02-10  9:30                     ` Thomas Petazzoni
  2017-02-10 13:21                       ` Lionel Flandrin
  0 siblings, 1 reply; 24+ messages in thread
From: Thomas Petazzoni @ 2017-02-10  9:30 UTC (permalink / raw)
  To: buildroot

Hello,

On Fri, 10 Feb 2017 10:10:31 +0100, Lionel Flandrin wrote:

> > I missed it on my first review, but it seems like you missed it as
> > well: we already have some logic in uboot.mk to call mkpimage. See the
> > BR2_TARGET_UBOOT_ALTERA_SOCFPGA_IMAGE_CRC option.
> > 
> > This should be extended rather than having two options doing the same
> > thing.  
> 
> I didn't miss it but the existing code is used for u-boot SPL
> generation, I didn't think there was an easy way to reuse it for
> "full" u-boot packaging (but admitedly my Make-foo is a bit
> weak). It's a different set of options.
> 
> The previous altera chips only had a 64K internal RAM which meant that
> you almost always had to use a SPL to bootstrap the bootloader. The
> newer chips however contain 256K of internal RAM so you can fit a full
> u-boot in a single stage quite snugly.

OK. Then I think we want something better indeed, because it's
completely impossible to understand if we have two separate options.

Here is what I would propose:

 1. Add an option BR2_TARGET_UBOOT_FORMAT_DTB_BIN so select
    u-boot-dtb.bin as the output format.

 2. Adjust the BR2_TARGET_UBOOT_ALTERA_SOCFPGA_IMAGE_CRC option logic
    so that it will mkpimage the SPL if there is a SPL, or mkpimage the
    full U-Boot if u-boot-dtb.bin is selected. Something like:

config BR2_TARGET_UBOOT_ALTERA_SOCFPGA_IMAGE_CRC
        bool "CRC U-Boot image for Altera SoC FPGA"
        depends on BR2_arm
        depends on BR2_TARGET_UBOOT_SPL || BR2_TARGET_UBOOT_FORMAT_DTB_BIN
        help

	  Pass the U-Boot image through the mkpimage tool to enable
	  booting on the Altera SoC FPGA based platforms.

	  On some platforms, it's the SPL that needs to be passed
	  through mkpimage. On some other platforms there is no SPL
	  because the internal SRAM is big enough to store the full
	  U-Boot. In this case, it's directly the full U-Boot image
	  that is passed through mkpimage.

	  Therefore, this option will convert the SPL image defined by
	  BR2_TARGET_UBOOT_SPL_NAME using mkpimage if
	  BR2_TARGET_UBOOT_SPL is enabled. Otherwise, it will convert
	  the full U-Boot image u-boot-dtb.bin if
	  BR2_TARGET_UBOOT_FORMAT_DTB_BIN is enabled.

And then in the .mk file, something like:

ifeq ($(BR2_TARGET_UBOOT_ALTERA_SOCFPGA_IMAGE_CRC),y)
ifeq ($(BR2_TARGET_UBOOT_SPL),y)
UBOOT_CRC_ALTERA_SOCFPGA_INPUT_IMAGES = $(call qstrip,$(BR2_TARGET_UBOOT_SPL_NAME))
else
UBOOT_CRC_ALTERA_SOCFPGA_INPUT_IMAGES = u-boot-dtb.bin
endif
define UBOOT_CRC_ALTERA_SOCFPGA_IMAGE
        $(foreach f,$(UBOOT_CRC_ALTERA_SOCFPGA_INPUT_IMAGES), \
                $(HOST_DIR)/usr/bin/mkpimage \
                        -o $(BINARIES_DIR)/$(notdir $(call qstrip,$(f))).crc \
                        $(@D)/$(call qstrip,$(f))
        )
endef
UBOOT_DEPENDENCIES += host-mkpimage
UBOOT_POST_INSTALL_IMAGES_HOOKS += UBOOT_CRC_ALTERA_SOCFPGA_IMAGE
endif

Could you try this, and verify it works for both the SPL and full
U-Boot image cases?

Thanks!

Thomas
-- 
Thomas Petazzoni, CTO, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [Buildroot] [PATCH 2/2] u-boot: Add support for Altera mkpimage generation
  2017-02-10  9:30                     ` Thomas Petazzoni
@ 2017-02-10 13:21                       ` Lionel Flandrin
  0 siblings, 0 replies; 24+ messages in thread
From: Lionel Flandrin @ 2017-02-10 13:21 UTC (permalink / raw)
  To: buildroot

On Fri, Feb 10, 2017 at 10:30:34AM +0100, Thomas Petazzoni wrote:
> Hello,
> 
> On Fri, 10 Feb 2017 10:10:31 +0100, Lionel Flandrin wrote:
> 
> > > I missed it on my first review, but it seems like you missed it as
> > > well: we already have some logic in uboot.mk to call mkpimage. See the
> > > BR2_TARGET_UBOOT_ALTERA_SOCFPGA_IMAGE_CRC option.
> > > 
> > > This should be extended rather than having two options doing the same
> > > thing.  
> > 
> > I didn't miss it but the existing code is used for u-boot SPL
> > generation, I didn't think there was an easy way to reuse it for
> > "full" u-boot packaging (but admitedly my Make-foo is a bit
> > weak). It's a different set of options.
> > 
> > The previous altera chips only had a 64K internal RAM which meant that
> > you almost always had to use a SPL to bootstrap the bootloader. The
> > newer chips however contain 256K of internal RAM so you can fit a full
> > u-boot in a single stage quite snugly.
> 
> OK. Then I think we want something better indeed, because it's
> completely impossible to understand if we have two separate options.
> 
> Here is what I would propose:
> 
>  1. Add an option BR2_TARGET_UBOOT_FORMAT_DTB_BIN so select
>     u-boot-dtb.bin as the output format.
> 
>  2. Adjust the BR2_TARGET_UBOOT_ALTERA_SOCFPGA_IMAGE_CRC option logic
>     so that it will mkpimage the SPL if there is a SPL, or mkpimage the
>     full U-Boot if u-boot-dtb.bin is selected. Something like:
> 
> config BR2_TARGET_UBOOT_ALTERA_SOCFPGA_IMAGE_CRC
>         bool "CRC U-Boot image for Altera SoC FPGA"
>         depends on BR2_arm
>         depends on BR2_TARGET_UBOOT_SPL || BR2_TARGET_UBOOT_FORMAT_DTB_BIN
>         help
> 
> 	  Pass the U-Boot image through the mkpimage tool to enable
> 	  booting on the Altera SoC FPGA based platforms.
> 
> 	  On some platforms, it's the SPL that needs to be passed
> 	  through mkpimage. On some other platforms there is no SPL
> 	  because the internal SRAM is big enough to store the full
> 	  U-Boot. In this case, it's directly the full U-Boot image
> 	  that is passed through mkpimage.
> 
> 	  Therefore, this option will convert the SPL image defined by
> 	  BR2_TARGET_UBOOT_SPL_NAME using mkpimage if
> 	  BR2_TARGET_UBOOT_SPL is enabled. Otherwise, it will convert
> 	  the full U-Boot image u-boot-dtb.bin if
> 	  BR2_TARGET_UBOOT_FORMAT_DTB_BIN is enabled.
> 
> And then in the .mk file, something like:
> 
> ifeq ($(BR2_TARGET_UBOOT_ALTERA_SOCFPGA_IMAGE_CRC),y)
> ifeq ($(BR2_TARGET_UBOOT_SPL),y)
> UBOOT_CRC_ALTERA_SOCFPGA_INPUT_IMAGES = $(call qstrip,$(BR2_TARGET_UBOOT_SPL_NAME))
> else
> UBOOT_CRC_ALTERA_SOCFPGA_INPUT_IMAGES = u-boot-dtb.bin
> endif
> define UBOOT_CRC_ALTERA_SOCFPGA_IMAGE
>         $(foreach f,$(UBOOT_CRC_ALTERA_SOCFPGA_INPUT_IMAGES), \
>                 $(HOST_DIR)/usr/bin/mkpimage \
>                         -o $(BINARIES_DIR)/$(notdir $(call qstrip,$(f))).crc \
>                         $(@D)/$(call qstrip,$(f))
>         )
> endef
> UBOOT_DEPENDENCIES += host-mkpimage
> UBOOT_POST_INSTALL_IMAGES_HOOKS += UBOOT_CRC_ALTERA_SOCFPGA_IMAGE
> endif
> 
> Could you try this, and verify it works for both the SPL and full
> U-Boot image cases?
> 
> Thanks!

Thank you for that, I'll give it a try and (hopefully) get back to you
with a new patch.

> Thomas
> -- 
> Thomas Petazzoni, CTO, Free Electrons
> Embedded Linux and Kernel engineering
> http://free-electrons.com

-- 
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/20170210/2cd7f85a/attachment.asc>

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [Buildroot] [PATCH 1/2] u-boot: add an option to generate u-boot-dtb.bin
  2017-01-30 10:33               ` [Buildroot] [PATCH 2/2] u-boot: Add support for Altera mkpimage generation Lionel Flandrin
  2017-02-09 22:33                 ` Thomas Petazzoni
@ 2017-02-13 13:59                 ` Lionel Flandrin
  2017-02-13 13:59                   ` [Buildroot] [PATCH 2/2] u-boot: add support for full image socfpga mkpimage support Lionel Flandrin
  2017-03-05 21:30                   ` [Buildroot] [PATCH 1/2] u-boot: add an option to generate u-boot-dtb.bin Thomas Petazzoni
  1 sibling, 2 replies; 24+ messages in thread
From: Lionel Flandrin @ 2017-02-13 13:59 UTC (permalink / raw)
  To: buildroot

Signed-off-by: Lionel Flandrin <lionel@svkt.org>
---
 boot/uboot/Config.in | 3 +++
 boot/uboot/uboot.mk  | 5 +++++
 2 files changed, 8 insertions(+)

diff --git a/boot/uboot/Config.in b/boot/uboot/Config.in
index 4e629c0ef..1aa2cb7b4 100644
--- a/boot/uboot/Config.in
+++ b/boot/uboot/Config.in
@@ -159,6 +159,9 @@ config BR2_TARGET_UBOOT_FORMAT_BIN
 	bool "u-boot.bin"
 	default y
 
+config BR2_TARGET_UBOOT_FORMAT_DTB_BIN
+	bool "u-boot-dtb.bin"
+
 config BR2_TARGET_UBOOT_FORMAT_DTB_IMG
 	bool "u-boot-dtb.img"
 
diff --git a/boot/uboot/uboot.mk b/boot/uboot/uboot.mk
index 6b9d54454..ac3b42e42 100644
--- a/boot/uboot/uboot.mk
+++ b/boot/uboot/uboot.mk
@@ -74,6 +74,11 @@ UBOOT_BINS += u-boot-dtb.img
 UBOOT_MAKE_TARGET += u-boot-dtb.img
 endif
 
+ifeq ($(BR2_TARGET_UBOOT_FORMAT_DTB_BIN),y)
+UBOOT_BINS += u-boot-dtb.bin
+UBOOT_MAKE_TARGET += u-boot-dtb.bin
+endif
+
 ifeq ($(BR2_TARGET_UBOOT_FORMAT_IMG),y)
 UBOOT_BINS += u-boot.img
 UBOOT_MAKE_TARGET += u-boot.img
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [Buildroot] [PATCH 2/2] u-boot: add support for full image socfpga mkpimage support
  2017-02-13 13:59                 ` [Buildroot] [PATCH 1/2] u-boot: add an option to generate u-boot-dtb.bin Lionel Flandrin
@ 2017-02-13 13:59                   ` Lionel Flandrin
  2017-02-13 14:27                     ` Thomas Petazzoni
  2017-02-13 15:33                     ` [Buildroot] [PATCH v2 2/2] u-boot: add support for full image socfpga mkpimage Lionel Flandrin
  2017-03-05 21:30                   ` [Buildroot] [PATCH 1/2] u-boot: add an option to generate u-boot-dtb.bin Thomas Petazzoni
  1 sibling, 2 replies; 24+ messages in thread
From: Lionel Flandrin @ 2017-02-13 13:59 UTC (permalink / raw)
  To: buildroot

Previously only SPL packaging was supported, now we can also wrap the
u-boot-dtb.bin if enabled.

Signed-off-by: Lionel Flandrin <lionel@svkt.org>
---
 boot/uboot/Config.in | 18 +++++++++++++++---
 boot/uboot/uboot.mk  | 10 +++++++++-
 2 files changed, 24 insertions(+), 4 deletions(-)

diff --git a/boot/uboot/Config.in b/boot/uboot/Config.in
index 1aa2cb7b4..51c0ccc6e 100644
--- a/boot/uboot/Config.in
+++ b/boot/uboot/Config.in
@@ -343,13 +343,25 @@ config BR2_TARGET_UBOOT_ZYNQ_IMAGE
 	  to be set.
 
 config BR2_TARGET_UBOOT_ALTERA_SOCFPGA_IMAGE_CRC
-	bool "CRC SPL image for Altera SoC FPGA"
+	bool "CRC image for Altera SoC FPGA (mkpimage)"
 	depends on BR2_arm
-	depends on BR2_TARGET_UBOOT_SPL
+	depends on BR2_TARGET_UBOOT_SPL || BR2_TARGET_UBOOT_FORMAT_DTB_BIN
 	help
-	  Generate SPL image fixed by the mkpimage tool to enable
+	  Pass the U-Boot image through the mkpimage tool to enable
 	  booting on the Altera SoC FPGA based platforms.
 
+	  On some platforms, it's the SPL that needs to be passed
+	  through mkpimage. On some other platforms there is no SPL
+	  because the internal SRAM is big enough to store the full
+	  U-Boot. In this case, it's directly the full U-Boot image
+	  that is passed through mkpimage.
+
+	  Therefore, this option will convert the SPL image defined by
+	  BR2_TARGET_UBOOT_SPL_NAME using mkpimage if
+	  BR2_TARGET_UBOOT_SPL is enabled. Otherwise, it will convert
+	  the full U-Boot image u-boot-dtb.bin if
+	  BR2_TARGET_UBOOT_FORMAT_DTB_BIN is enabled.
+
 menuconfig BR2_TARGET_UBOOT_ENVIMAGE
 	bool "Environment image"
 	help
diff --git a/boot/uboot/uboot.mk b/boot/uboot/uboot.mk
index ac3b42e42..1e22eaa8e 100644
--- a/boot/uboot/uboot.mk
+++ b/boot/uboot/uboot.mk
@@ -262,9 +262,17 @@ UBOOT_POST_INSTALL_IMAGES_HOOKS += UBOOT_GENERATE_ZYNQ_IMAGE
 endif
 
 ifeq ($(BR2_TARGET_UBOOT_ALTERA_SOCFPGA_IMAGE_CRC),y)
+ifeq ($(BR2_TARGET_UBOOT_SPL),y)
+UBOOT_CRC_ALTERA_SOCFPGA_INPUT_IMAGES = $(call qstrip,$(BR2_TARGET_UBOOT_SPL_NAME))
+UBOOT_CRC_ALTERA_SOCFPGA_HEADER_VERSION = 0
+else
+UBOOT_CRC_ALTERA_SOCFPGA_INPUT_IMAGES = u-boot-dtb.bin
+UBOOT_CRC_ALTERA_SOCFPGA_HEADER_VERSION = 1
+endif
 define UBOOT_CRC_ALTERA_SOCFPGA_IMAGE
-	$(foreach f,$(call qstrip,$(BR2_TARGET_UBOOT_SPL_NAME)), \
+	$(foreach f,$(UBOOT_CRC_ALTERA_SOCFPGA_INPUT_IMAGES), \
 		$(HOST_DIR)/usr/bin/mkpimage \
+			-v $(UBOOT_CRC_ALTERA_SOCFPGA_HEADER_VERSION) \
 			-o $(BINARIES_DIR)/$(notdir $(call qstrip,$(f))).crc \
 			$(@D)/$(call qstrip,$(f))
 	)
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [Buildroot] [PATCH 2/2] u-boot: add support for full image socfpga mkpimage support
  2017-02-13 13:59                   ` [Buildroot] [PATCH 2/2] u-boot: add support for full image socfpga mkpimage support Lionel Flandrin
@ 2017-02-13 14:27                     ` Thomas Petazzoni
  2017-02-13 14:57                       ` Lionel Flandrin
  2017-02-13 15:33                     ` [Buildroot] [PATCH v2 2/2] u-boot: add support for full image socfpga mkpimage Lionel Flandrin
  1 sibling, 1 reply; 24+ messages in thread
From: Thomas Petazzoni @ 2017-02-13 14:27 UTC (permalink / raw)
  To: buildroot

Hello,

Thanks for this new iteration!

On Mon, 13 Feb 2017 14:59:34 +0100, Lionel Flandrin wrote:

>  ifeq ($(BR2_TARGET_UBOOT_ALTERA_SOCFPGA_IMAGE_CRC),y)
> +ifeq ($(BR2_TARGET_UBOOT_SPL),y)
> +UBOOT_CRC_ALTERA_SOCFPGA_INPUT_IMAGES = $(call qstrip,$(BR2_TARGET_UBOOT_SPL_NAME))
> +UBOOT_CRC_ALTERA_SOCFPGA_HEADER_VERSION = 0
> +else
> +UBOOT_CRC_ALTERA_SOCFPGA_INPUT_IMAGES = u-boot-dtb.bin
> +UBOOT_CRC_ALTERA_SOCFPGA_HEADER_VERSION = 1
> +endif

So when the SPL is used, the header version should always be 0, and
when the full U-Boot is used directly, the header version should always
be 1 ?

I thought 0 was for older SoCs, and 1 for newer SoCs. Or are we sure
that SPL booting will only ever be used on older SoCs, and direct U-Boot
booting will only be used on newer SoCs ?

Thomas
-- 
Thomas Petazzoni, CTO, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [Buildroot] [PATCH 2/2] u-boot: add support for full image socfpga mkpimage support
  2017-02-13 14:27                     ` Thomas Petazzoni
@ 2017-02-13 14:57                       ` Lionel Flandrin
  2017-02-13 15:20                         ` Thomas Petazzoni
  0 siblings, 1 reply; 24+ messages in thread
From: Lionel Flandrin @ 2017-02-13 14:57 UTC (permalink / raw)
  To: buildroot

On Mon, Feb 13, 2017 at 03:27:47PM +0100, Thomas Petazzoni wrote:
> Hello,

Hello Thomas,

> Thanks for this new iteration!
> 
> On Mon, 13 Feb 2017 14:59:34 +0100, Lionel Flandrin wrote:
> 
> >  ifeq ($(BR2_TARGET_UBOOT_ALTERA_SOCFPGA_IMAGE_CRC),y)
> > +ifeq ($(BR2_TARGET_UBOOT_SPL),y)
> > +UBOOT_CRC_ALTERA_SOCFPGA_INPUT_IMAGES = $(call qstrip,$(BR2_TARGET_UBOOT_SPL_NAME))
> > +UBOOT_CRC_ALTERA_SOCFPGA_HEADER_VERSION = 0
> > +else
> > +UBOOT_CRC_ALTERA_SOCFPGA_INPUT_IMAGES = u-boot-dtb.bin
> > +UBOOT_CRC_ALTERA_SOCFPGA_HEADER_VERSION = 1
> > +endif
> 
> So when the SPL is used, the header version should always be 0, and
> when the full U-Boot is used directly, the header version should always
> be 1 ?
> 
> I thought 0 was for older SoCs, and 1 for newer SoCs. Or are we sure
> that SPL booting will only ever be used on older SoCs, and direct U-Boot
> booting will only be used on newer SoCs ?

Yeah I considered adding an option for selecting the version,
technically it could go either way but in practice I can't think of a
situation where you'd want a v1 header with a SPL or vice versa.

Basically:
Cyclone V/Arria V ->  64K internal RAM + header v0
Arria 10          -> 256K internal RAM + header v1

I believe the main reason for the v1 header is simply to allow file
sizes greater than 64k.

Unless you managed to create a full u-boot build smaller than 64K
you'd never be able to make a v0 image without SPL.

You could technically create a v1 SPL image (which the current
Makefile wouldn't allow) but I'm not sure why anybody would want that.

So I thought adding an option might end up being more confusing than
helpful even if it results in a bit of "magic" in the makefile.


On a completely unrelated tangent: I kept the previous naming
convention for the resulting image, which creates ".crc"
files. Changing this would break build systems that use the SPL images
but I thought it was a rather unexpected extension for these files. My
previous patch used ".mkpimage". Altera uses "-mkpimage.bin".

That being said it might not be worth breaking people's builds over
that.

> Thomas

-- 
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/20170213/cb2bc337/attachment.asc>

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [Buildroot] [PATCH 2/2] u-boot: add support for full image socfpga mkpimage support
  2017-02-13 14:57                       ` Lionel Flandrin
@ 2017-02-13 15:20                         ` Thomas Petazzoni
  0 siblings, 0 replies; 24+ messages in thread
From: Thomas Petazzoni @ 2017-02-13 15:20 UTC (permalink / raw)
  To: buildroot

Hello,

On Mon, 13 Feb 2017 15:57:16 +0100, Lionel Flandrin wrote:

> > Thanks for this new iteration!
> > 
> > On Mon, 13 Feb 2017 14:59:34 +0100, Lionel Flandrin wrote:
> >   
> > >  ifeq ($(BR2_TARGET_UBOOT_ALTERA_SOCFPGA_IMAGE_CRC),y)
> > > +ifeq ($(BR2_TARGET_UBOOT_SPL),y)
> > > +UBOOT_CRC_ALTERA_SOCFPGA_INPUT_IMAGES = $(call qstrip,$(BR2_TARGET_UBOOT_SPL_NAME))
> > > +UBOOT_CRC_ALTERA_SOCFPGA_HEADER_VERSION = 0
> > > +else
> > > +UBOOT_CRC_ALTERA_SOCFPGA_INPUT_IMAGES = u-boot-dtb.bin
> > > +UBOOT_CRC_ALTERA_SOCFPGA_HEADER_VERSION = 1
> > > +endif  
> > 
> > So when the SPL is used, the header version should always be 0, and
> > when the full U-Boot is used directly, the header version should always
> > be 1 ?
> > 
> > I thought 0 was for older SoCs, and 1 for newer SoCs. Or are we sure
> > that SPL booting will only ever be used on older SoCs, and direct U-Boot
> > booting will only be used on newer SoCs ?  
> 
> Yeah I considered adding an option for selecting the version,
> technically it could go either way but in practice I can't think of a
> situation where you'd want a v1 header with a SPL or vice versa.
> 
> Basically:
> Cyclone V/Arria V ->  64K internal RAM + header v0
> Arria 10          -> 256K internal RAM + header v1
> 
> I believe the main reason for the v1 header is simply to allow file
> sizes greater than 64k.
> 
> Unless you managed to create a full u-boot build smaller than 64K
> you'd never be able to make a v0 image without SPL.
> 
> You could technically create a v1 SPL image (which the current
> Makefile wouldn't allow) but I'm not sure why anybody would want that.
> 
> So I thought adding an option might end up being more confusing than
> helpful even if it results in a bit of "magic" in the makefile.

OK, thanks for the explanation. It makes sense to me. However, I
believe this should be explicitly mentioned in the help text of the
Config.in option.

> On a completely unrelated tangent: I kept the previous naming
> convention for the resulting image, which creates ".crc"
> files. Changing this would break build systems that use the SPL images
> but I thought it was a rather unexpected extension for these files. My
> previous patch used ".mkpimage". Altera uses "-mkpimage.bin".
> 
> That being said it might not be worth breaking people's builds over
> that.

Yeah, just keep the existing .crc extension. The other extension you
propose don't really bring any benefit, and keeping .crc makes sure
things won't break for existing users. As long as the generated file
name is mentioned in the help text of the Config.in option, we're good
IMO.

Thanks!

Thomas
-- 
Thomas Petazzoni, CTO, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [Buildroot] [PATCH v2 2/2] u-boot: add support for full image socfpga mkpimage
  2017-02-13 13:59                   ` [Buildroot] [PATCH 2/2] u-boot: add support for full image socfpga mkpimage support Lionel Flandrin
  2017-02-13 14:27                     ` Thomas Petazzoni
@ 2017-02-13 15:33                     ` Lionel Flandrin
  2017-03-05 21:31                       ` Thomas Petazzoni
  1 sibling, 1 reply; 24+ messages in thread
From: Lionel Flandrin @ 2017-02-13 15:33 UTC (permalink / raw)
  To: buildroot

Previously only SPL packaging was supported, now we can also wrap the
u-boot-dtb.bin if enabled.

Signed-off-by: Lionel Flandrin <lionel@svkt.org>

---
Changes v1 -> v2:
  - Improve kconfig help by describing the behaviour of the makefile more
    precisely.
---
 boot/uboot/Config.in | 20 +++++++++++++++++---
 boot/uboot/uboot.mk  | 10 +++++++++-
 2 files changed, 26 insertions(+), 4 deletions(-)

diff --git a/boot/uboot/Config.in b/boot/uboot/Config.in
index 1aa2cb7b4..66c08a995 100644
--- a/boot/uboot/Config.in
+++ b/boot/uboot/Config.in
@@ -343,13 +343,27 @@ config BR2_TARGET_UBOOT_ZYNQ_IMAGE
 	  to be set.
 
 config BR2_TARGET_UBOOT_ALTERA_SOCFPGA_IMAGE_CRC
-	bool "CRC SPL image for Altera SoC FPGA"
+	bool "CRC image for Altera SoC FPGA (mkpimage)"
 	depends on BR2_arm
-	depends on BR2_TARGET_UBOOT_SPL
+	depends on BR2_TARGET_UBOOT_SPL || BR2_TARGET_UBOOT_FORMAT_DTB_BIN
 	help
-	  Generate SPL image fixed by the mkpimage tool to enable
+	  Pass the U-Boot image through the mkpimage tool to enable
 	  booting on the Altera SoC FPGA based platforms.
 
+	  On some platforms, it's the SPL that needs to be passed
+	  through mkpimage. On some other platforms there is no SPL
+	  because the internal SRAM is big enough to store the full
+	  U-Boot. In this case, it's directly the full U-Boot image
+	  that is passed through mkpimage.
+
+	  If BR2_TARGET_UBOOT_SPL is enabled then BR2_TARGET_UBOOT_SPL_NAME is
+	  converted by mkpimage using header version 0.
+
+	  Otherwise the full u-boot-dtb.bin is converted using mkpimage header
+	  version 1.
+
+	  In either case the resulting file will be given a .crc extension.
+
 menuconfig BR2_TARGET_UBOOT_ENVIMAGE
 	bool "Environment image"
 	help
diff --git a/boot/uboot/uboot.mk b/boot/uboot/uboot.mk
index ac3b42e42..1e22eaa8e 100644
--- a/boot/uboot/uboot.mk
+++ b/boot/uboot/uboot.mk
@@ -262,9 +262,17 @@ UBOOT_POST_INSTALL_IMAGES_HOOKS += UBOOT_GENERATE_ZYNQ_IMAGE
 endif
 
 ifeq ($(BR2_TARGET_UBOOT_ALTERA_SOCFPGA_IMAGE_CRC),y)
+ifeq ($(BR2_TARGET_UBOOT_SPL),y)
+UBOOT_CRC_ALTERA_SOCFPGA_INPUT_IMAGES = $(call qstrip,$(BR2_TARGET_UBOOT_SPL_NAME))
+UBOOT_CRC_ALTERA_SOCFPGA_HEADER_VERSION = 0
+else
+UBOOT_CRC_ALTERA_SOCFPGA_INPUT_IMAGES = u-boot-dtb.bin
+UBOOT_CRC_ALTERA_SOCFPGA_HEADER_VERSION = 1
+endif
 define UBOOT_CRC_ALTERA_SOCFPGA_IMAGE
-	$(foreach f,$(call qstrip,$(BR2_TARGET_UBOOT_SPL_NAME)), \
+	$(foreach f,$(UBOOT_CRC_ALTERA_SOCFPGA_INPUT_IMAGES), \
 		$(HOST_DIR)/usr/bin/mkpimage \
+			-v $(UBOOT_CRC_ALTERA_SOCFPGA_HEADER_VERSION) \
 			-o $(BINARIES_DIR)/$(notdir $(call qstrip,$(f))).crc \
 			$(@D)/$(call qstrip,$(f))
 	)
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [Buildroot] [PATCH 1/2] u-boot: add an option to generate u-boot-dtb.bin
  2017-02-13 13:59                 ` [Buildroot] [PATCH 1/2] u-boot: add an option to generate u-boot-dtb.bin Lionel Flandrin
  2017-02-13 13:59                   ` [Buildroot] [PATCH 2/2] u-boot: add support for full image socfpga mkpimage support Lionel Flandrin
@ 2017-03-05 21:30                   ` Thomas Petazzoni
  1 sibling, 0 replies; 24+ messages in thread
From: Thomas Petazzoni @ 2017-03-05 21:30 UTC (permalink / raw)
  To: buildroot

Hello,

On Mon, 13 Feb 2017 14:59:33 +0100, Lionel Flandrin wrote:
> Signed-off-by: Lionel Flandrin <lionel@svkt.org>
> ---
>  boot/uboot/Config.in | 3 +++
>  boot/uboot/uboot.mk  | 5 +++++
>  2 files changed, 8 insertions(+)

Applied to master, thanks.

Thomas
-- 
Thomas Petazzoni, CTO, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [Buildroot] [PATCH v2 2/2] u-boot: add support for full image socfpga mkpimage
  2017-02-13 15:33                     ` [Buildroot] [PATCH v2 2/2] u-boot: add support for full image socfpga mkpimage Lionel Flandrin
@ 2017-03-05 21:31                       ` Thomas Petazzoni
  0 siblings, 0 replies; 24+ messages in thread
From: Thomas Petazzoni @ 2017-03-05 21:31 UTC (permalink / raw)
  To: buildroot

Hello,

On Mon, 13 Feb 2017 16:33:29 +0100, Lionel Flandrin wrote:
> Previously only SPL packaging was supported, now we can also wrap the
> u-boot-dtb.bin if enabled.
> 
> Signed-off-by: Lionel Flandrin <lionel@svkt.org>

I've extended the commit log quite a bit to explain what is going on.

> +	  If BR2_TARGET_UBOOT_SPL is enabled then BR2_TARGET_UBOOT_SPL_NAME is
> +	  converted by mkpimage using header version 0.
> +
> +	  Otherwise the full u-boot-dtb.bin is converted using mkpimage header
> +	  version 1.
> +
> +	  In either case the resulting file will be given a .crc extension.

These paragraphs were a bit too wide, so I rewrapped them.

Also, could you provide a configuration to test the build of the header
version 0 situation, and another to test the build of the header
version 1 situation ?

I'm not familiar enough with the various SoCFPGA SoCs/boards to know
which one is in which situation.

Thanks!

Thomas
-- 
Thomas Petazzoni, CTO, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

^ permalink raw reply	[flat|nested] 24+ messages in thread

end of thread, other threads:[~2017-03-05 21:31 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-01-26 11:16 [Buildroot] [PATCH 1/3] mkpimage: rewrite to support header version 1 Lionel Flandrin
2017-01-26 11:17 ` [Buildroot] [PATCH 2/3] u-boot: Add support for Altera mkpimage generation Lionel Flandrin
2017-01-26 11:17   ` [Buildroot] [PATCH 3/3] DEVELOPERS: Add Lionel Flandrin to package/mkpimage Lionel Flandrin
2017-01-26 11:25 ` [Buildroot] [PATCH 1/3] mkpimage: rewrite to support header version 1 Lionel Flandrin
2017-01-26 11:28   ` Lionel Flandrin
2017-01-27  8:17     ` Thomas Petazzoni
2017-01-27  9:52       ` Lionel Flandrin
2017-01-28  8:42         ` Thomas Petazzoni
2017-01-28 11:27           ` Lionel Flandrin
2017-01-30 10:33             ` [Buildroot] [PATCH 1/2] mkpimage: bump to latest barebox version Lionel Flandrin
2017-01-30 10:33               ` [Buildroot] [PATCH 2/2] u-boot: Add support for Altera mkpimage generation Lionel Flandrin
2017-02-09 22:33                 ` Thomas Petazzoni
2017-02-10  9:10                   ` Lionel Flandrin
2017-02-10  9:30                     ` Thomas Petazzoni
2017-02-10 13:21                       ` Lionel Flandrin
2017-02-13 13:59                 ` [Buildroot] [PATCH 1/2] u-boot: add an option to generate u-boot-dtb.bin Lionel Flandrin
2017-02-13 13:59                   ` [Buildroot] [PATCH 2/2] u-boot: add support for full image socfpga mkpimage support Lionel Flandrin
2017-02-13 14:27                     ` Thomas Petazzoni
2017-02-13 14:57                       ` Lionel Flandrin
2017-02-13 15:20                         ` Thomas Petazzoni
2017-02-13 15:33                     ` [Buildroot] [PATCH v2 2/2] u-boot: add support for full image socfpga mkpimage Lionel Flandrin
2017-03-05 21:31                       ` Thomas Petazzoni
2017-03-05 21:30                   ` [Buildroot] [PATCH 1/2] u-boot: add an option to generate u-boot-dtb.bin Thomas Petazzoni
2017-02-09 22:34               ` [Buildroot] [PATCH 1/2] mkpimage: bump to latest barebox version Thomas Petazzoni

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.