[Buildroot] [PATCH 1/3] mkpimage: rewrite to support header version 1
Lionel Flandrin
lionel at svkt.org
Thu Jan 26 11:25:17 UTC 2017
On Thu, Jan 26, 2017 at 12:16:02PM +0100, Lionel Flandrin wrote:
> mkpimage is a proprietary tool part of Altera's Embedded Development
> Suite which is used to generate the image files supported by their
> BootROMs.
>
> Newer versions of their SoCs (such as the Arria 10) use header version
> 1 which was not supported by the previous version of this tool.
>
> This new version supports header version 1, improves error handling
> and tweaks the output to bring it closer to Altera's own tool. In
> particular the padding calculations have been changed. In all the
> configurations tested this program and Altera's mkpimage produce
> exactly the same files (while the previous version didn't).
>
> Signed-off-by: Lionel Flandrin <lionel at svkt.org>
> ---
> package/mkpimage/mkpimage.c | 767 ++++++++++++++++++++++++++++---------------
> package/mkpimage/mkpimage.mk | 3 -
> 2 files changed, 511 insertions(+), 259 deletions(-)
>
> diff --git a/package/mkpimage/mkpimage.c b/package/mkpimage/mkpimage.c
> index 1a7a66d98..06e36040c 100644
> --- a/package/mkpimage/mkpimage.c
> +++ b/package/mkpimage/mkpimage.c
> @@ -1,287 +1,542 @@
> +/* Replacement for altera's proprietary mkpimage (part of their EDS)
> + *
> + * Create an Altera BootROM-compatible image of the Second Stage Boot
> + * Loader (SSBL).
> + *
> + * This program should generate the same output as Altera's mkpimage
> + * version 16.1 (build 196). If it doesn't it's a bug.
> + *
> + * The original version of this program was part of barebox.
> + *
> + * Distributed under the GNU GPL v2.
> + */
> +
> #include <stdio.h>
> -#include <unistd.h>
> #include <getopt.h>
> #include <stdlib.h>
> #include <stdint.h>
> #include <string.h>
> +#include <unistd.h>
> +#include <fcntl.h>
> #include <errno.h>
> -#include <sys/types.h>
> #include <sys/stat.h>
> -#include <fcntl.h>
> -#include <endian.h>
>
> -#define VALIDATION_WORD 0x31305341
> +#define MKPIMAGE_VERSION "1.0"
>
> -#define MAX_IMAGE_SIZE (60 * 1024 - 4)
> +#define VALIDATION_WORD 0x31305341
>
> -static int add_barebox_header;
> +struct socfpga_header_v0 {
> + uint8_t validation_word[4];
> + uint8_t version;
> + uint8_t flags;
> + uint8_t program_length[2];
> + uint8_t spare[2];
> + uint8_t checksum[2];
> +};
>
> -struct socfpga_header {
> - uint8_t validation_word[4];
> - uint8_t version;
> - uint8_t flags;
> - uint8_t program_length[2];
> - uint8_t spare[2];
> - uint8_t checksum[2];
> +struct socfpga_header_v1 {
> + uint8_t validation_word[4];
> + uint8_t version;
> + uint8_t flags;
> + uint8_t header_length[2];
> + uint8_t program_length[4];
> + uint8_t program_offset[4];
> + uint8_t spare[2];
> + uint8_t checksum[2];
> };
>
> static uint32_t bb_header[] = {
> - 0xea00007e, /* b 0x200 */
> - 0xeafffffe, /* 1: b 1b */
> - 0xeafffffe, /* 1: b 1b */
> - 0xeafffffe, /* 1: b 1b */
> - 0xeafffffe, /* 1: b 1b */
> - 0xeafffffe, /* 1: b 1b */
> - 0xeafffffe, /* 1: b 1b */
> - 0xeafffffe, /* 1: b 1b */
> - 0x65726162, /* 'bare' */
> - 0x00786f62, /* 'box\0' */
> - 0x00000000, /* padding */
> - 0x00000000, /* padding */
> - 0x00000000, /* padding */
> - 0x00000000, /* padding */
> - 0x00000000, /* padding */
> - 0x00000000, /* padding */
> - 0x00000000, /* socfpga header */
> - 0x00000000, /* socfpga header */
> - 0x00000000, /* socfpga header */
> - 0xea00006b, /* entry. b 0x200 */
> + 0xea00007e, /* b 0x200 */
> + 0xeafffffe, /* 1: b 1b */
> + 0xeafffffe, /* 1: b 1b */
> + 0xeafffffe, /* 1: b 1b */
> + 0xeafffffe, /* 1: b 1b */
> + 0xeafffffe, /* 1: b 1b */
> + 0xeafffffe, /* 1: b 1b */
> + 0xeafffffe, /* 1: b 1b */
> + 0x65726162, /* 'bare' */
> + 0x00786f62, /* 'box\0' */
> + 0x00000000, /* padding */
> + 0x00000000, /* padding */
> + 0x00000000, /* padding */
> + 0x00000000, /* padding */
> + 0x00000000, /* padding */
> + 0x00000000, /* padding */
> + 0x00000000, /* socfpga header */
> + 0x00000000, /* socfpga header */
> + 0x00000000, /* socfpga header */
> + 0xea00006b, /* entry. b 0x200 */
> };
>
> -static int read_full(int fd, void *buf, size_t size)
> -{
> - size_t insize = size;
> - int now;
> - int total = 0;
> -
> - while (size) {
> - now = read(fd, buf, size);
> - if (now == 0)
> - return total;
> - if (now < 0)
> - return now;
> - total += now;
> - size -= now;
> - buf += now;
> - }
> -
> - return insize;
> +static int add_file(int outfd,
> + const char *path,
> + unsigned header_version,
> + size_t alignment,
> + int barebox,
> + unsigned long entry_offset);
> +static void add_socfpga_header_v0(uint8_t *buf, size_t size);
> +static void add_socfpga_header_v1(uint8_t *buf,
> + size_t size,
> + unsigned long entry_offset);
> +static uint32_t crc32(uint8_t *buf, size_t length);
> +static int write_all(int fd, uint8_t *buf, size_t size);
> +
> +static void usage(const char *bin) {
> + fprintf(stderr,
> +"Buildroot mkpimage v" MKPIMAGE_VERSION "\n"
> +"\n"
> +"Usage:\n"
> +" Create quad image:\n"
> +" %1$s [options] -H <num> -o <outfile> <infile> "
> +"<infile> <infile> <infile>\n"
> +" Create single image:\n"
> +" %1$s [options] -H <num> -o <outfile> <infile>\n"
> +"\n"
> +"Options:\n"
> +"\n"
> +"-h (--help) Display this help message and exit\n"
> +"-H (--header-version) <num> Header version to be created\n"
> +" - Arria/Cyclone V = 0\n"
> +" - Arria 10 = 1\n"
> +" [default: 0]\n"
> +"-a (--alignment) <num> Address alignment in kilobytes, valid value\n"
> +" starts from 64, 128, 256 etc, override if the\n"
> +" NAND flash has a larger block size\n"
> +" [default: 64 for header v0, 256 for v1]\n"
> +"-o (--output) <outfile> Output file. Relative and absolute path\n"
> +" supported\n"
> +"-b (--barebox) Add barebox header\n"
> +"-O (--offset) <num> Program entry offset relative to start of\n"
> +" header (0x40). Used for header version 1 only.\n"
> +" [default: 20, min: 20]\n", bin);
> }
>
> -static int write_full(int fd, void *buf, size_t size)
> -{
> - size_t insize = size;
> - int now;
> -
> - while (size) {
> - now = write(fd, buf, size);
> - if (now <= 0)
> - return now;
> - size -= now;
> - buf += now;
> - }
> -
> - return insize;
> +
> +int main(int argc, char **argv) {
> + static struct option opts[] = {
> + {"help", no_argument, NULL, 'h' },
> + {"header-version", required_argument, NULL, 'H' },
> + {"alignement", required_argument, NULL, 'a' },
> + {"output", required_argument, NULL, 'o' },
> + {"barebox", no_argument, NULL, 'b' },
Just noticed I forgot "offset" here, I'm going to send a new patch
> + {NULL, 0, NULL, 0 },
> + };
> +
> + int opt;
> + int barebox = 0;
> + unsigned header_version = 0;
> + size_t alignment = 0;
> + int alignment_set = 0;
> + const char *outfile = NULL;
> + unsigned nfiles;
> + unsigned long entry_offset = 20;
> + int entry_offset_set = 0;
> + int outfd;
> + unsigned i;
> +
> + while ((opt = getopt_long(argc, argv, "hH:a:dfo:bO:", opts, NULL)) != -1) {
> + switch (opt) {
> + case 'H':
> + header_version = optarg[0] - '0';
> + if (strlen(optarg) != 1 ||
> + (header_version != 0 && header_version != 1)) {
> + fprintf(stderr, "Invalid header version: %s\n\n", optarg);
> + usage(argv[0]);
> + return EXIT_FAILURE;
> + }
> + break;
> + case 'a':
> + {
> + char *endptr;
> +
> + alignment = strtoul(optarg, &endptr, 0);
> +
> + if (*endptr != '\0' || alignment == 0) {
> + fprintf(stderr, "Invalid alignment: %s\n\n", optarg);
> + usage(argv[0]);
> + return EXIT_FAILURE;
> + }
> +
> + alignment *= 1024;
> + alignment_set = 1;
> + }
> + break;
> + case 'b':
> + barebox = 1;
> + break;
> + case 'o':
> + outfile = optarg;
> + break;
> + case 'O':
> + {
> + char *endptr;
> +
> + entry_offset = strtoul(optarg, &endptr, 0);
> +
> + if (*endptr != '\0' || entry_offset < 20) {
> + fprintf(stderr, "Invalid entry offset: %s\n\n", optarg);
> + usage(argv[0]);
> + return EXIT_FAILURE;
> + }
> +
> + entry_offset_set = 1;
> + }
> + break;
> + case 'h':
> + default:
> + usage(argv[0]);
> + return EXIT_FAILURE;
> + }
> + }
> +
> + if (outfile == NULL) {
> + fprintf(stderr, "Missing output file name\n\n");
> + usage(argv[0]);
> + return EXIT_FAILURE;
> + }
> +
> + if (!alignment_set) {
> + if (header_version == 0) {
> + /* Default to 64K */
> + alignment = 64 * 1024;
> + } else {
> + /* V1 defaults to 256K */
> + alignment = 256 * 1024;
> + }
> + }
> +
> + if (entry_offset_set && header_version == 0) {
> + fprintf(stderr,
> + "Error: entry offset is not available in header version 0\n\n");
> + usage(argv[0]);
> + return EXIT_FAILURE;
> + }
> +
> + nfiles = argc - optind;
> +
> + if (nfiles != 1 && nfiles != 4) {
> + fprintf(stderr,
> + "Wrong number of input files: expected 1 or 4, got %u\n\n",
> + nfiles);
> + usage(argv[0]);
> + return EXIT_FAILURE;
> + }
> +
> + outfd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, 0644);
> + if (outfd == -1) {
> + fprintf(stderr,
> + "Couldn't open '%s' for writing: %s\n",
> + outfile, strerror(errno));
> + return EXIT_FAILURE;
> + }
> +
> + /* Barebox's version of this program doesn't pad the output up to
> + * alignment, however Altera's mkpimage does. */
> + if (ftruncate(outfd, alignment * nfiles) == -1) {
> + fprintf(stderr,
> + "Couldn't truncate '%s' to %lu: %s\n",
> + outfile, alignment * nfiles, strerror(errno));
> + goto unlink;
> + }
> +
> + for (i = 0; i < nfiles; i++) {
> + if (lseek(outfd, i * alignment, SEEK_SET) == -1) {
> + fprintf(stderr,
> + "Couldn't seek '%s' to %lu: %s\n",
> + outfile, i * alignment, strerror(errno));
> + goto unlink;
> + }
> +
> + if (add_file(outfd,
> + argv[optind + i],
> + header_version,
> + alignment,
> + barebox,
> + entry_offset) == -1) {
> + goto unlink;
> + }
> + }
> +
> + close(outfd);
> +
> + return EXIT_SUCCESS;
> +
> + unlink:
> + /* Something went wrong, delete the output*/
> + close(outfd);
> + unlink(outfile);
> + return EXIT_FAILURE;
> }
>
> -static uint32_t crc_table[256] = {
> - 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
> - 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
> - 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7,
> - 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
> - 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3,
> - 0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
> - 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef,
> - 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
> - 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb,
> - 0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
> - 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
> - 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
> - 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4,
> - 0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
> - 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08,
> - 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
> - 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc,
> - 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
> - 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050,
> - 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
> - 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
> - 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
> - 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1,
> - 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
> - 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5,
> - 0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
> - 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9,
> - 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
> - 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd,
> - 0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
> - 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
> - 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
> - 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2,
> - 0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
> - 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e,
> - 0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
> - 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a,
> - 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
> - 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676,
> - 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
> - 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
> - 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
> - 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
> -};
> +static int add_file(int outfd,
> + const char *path,
> + unsigned header_version,
> + size_t alignment,
> + int barebox,
> + unsigned long entry_offset) {
> + int fd = -1;
> + struct stat st;
> + int ret = -1;
> + size_t file_size;
> + size_t out_size;
> + uint8_t *buffer = NULL;
> + uint8_t *rbuffer = NULL;
> + size_t nread = 0;
> +
> + fd = open(path, O_RDONLY);
> +
> + if (fd == -1) {
> + fprintf(stderr, "Couldn't open '%s' for reading: %s\n",
> + path, strerror(errno));
> + goto exit;
> + }
> +
> + if (fstat(fd, &st) == -1) {
> + fprintf(stderr,
> + "Couldn't stat '%s': %s\n",
> + path, strerror(errno));
> + goto exit;
> + }
> +
> + file_size = st.st_size;
> +
> + /* Add room for 32bit CRC */
> + out_size = file_size + sizeof(uint32_t);
> +
> + if (barebox) {
> + out_size += 512;
> + }
> +
> + /* Barebox's version of this program pads the binary to a multiple
> + * of 4bytes, however altera's mkpimage pads to 32bytes. I'm not
> + * sure if it makes a difference in practice but I prefer to be as
> + * close as possible to the reference.
> + */
> + out_size = (out_size + 31UL) & (~31UL);
> +
> + if (out_size > alignment) {
> + fprintf(stderr,
> + "Error: File '%s' is too big to fit the alignment of %luKB\n",
> + path,
> + alignment / 1024);
> + goto exit;
> + }
> +
> + buffer = malloc(out_size);
> + if (buffer == NULL) {
> + fprintf(stderr, "malloc(%lu) failed\n", out_size);
> + goto exit;
> + }
> +
> + memset(buffer, 0, out_size);
> +
> + if (barebox) {
> + memcpy(buffer, bb_header, sizeof(bb_header));
> + rbuffer = buffer + 512;
> + } else {
> + rbuffer = buffer;
> + }
> +
> + while (nread < file_size) {
> + ssize_t n = read(fd, rbuffer + nread, file_size - nread);
> +
> + if (n < 0) {
> + fprintf(stderr, "Error while reading '%s': %s\n",
> + path, strerror(errno));
> + goto exit;
> + }
> +
> + if (n == 0) {
> + fprintf(stderr, "Error while reading '%s': %s\n",
> + path, "Short read");
> + goto exit;
> + }
> +
> + nread += (size_t)n;
> + }
> +
> + if (header_version == 0) {
> + add_socfpga_header_v0(buffer, out_size);
> + } else {
> + add_socfpga_header_v1(buffer, out_size, entry_offset);
> + }
> +
> + if (write_all(outfd, buffer, out_size) == -1) {
> + goto exit;
> + }
> +
> + ret = 0;
> + exit:
> + if (buffer != NULL) {
> + free(buffer);
> + }
> +
> + if (fd >= 0) {
> + close(fd);
> + }
> +
> + return ret;
> +}
>
> -uint32_t crc32(uint32_t crc, void *_buf, int length)
> +static void add_socfpga_header_v0(uint8_t *buf, size_t size)
> {
> - uint8_t *buf = _buf;
> -
> - while (length--)
> - crc = crc << 8 ^ crc_table[(crc >> 24 ^ *(buf++)) & 0xff];
> -
> - return crc;
> + struct socfpga_header_v0 *header = (void*)(buf + 0x40);
> + uint32_t crc;
> + uint32_t crc_idx;
> + unsigned checksum;
> + size_t length = size >> 2;
> + size_t i;
> +
> + header->validation_word[0] = VALIDATION_WORD & 0xff;
> + header->validation_word[1] = (VALIDATION_WORD >> 8) & 0xff;
> + header->validation_word[2] = (VALIDATION_WORD >> 16) & 0xff;
> + header->validation_word[3] = (VALIDATION_WORD >> 24) & 0xff;
> + header->version = 0;
> + header->flags = 0;
> + header->program_length[0] = length & 0xff;
> + header->program_length[1] = (length >> 8) & 0xff;
> + header->spare[0] = 0;
> + header->spare[1] = 0;
> +
> + /* Header checksum */
> + checksum = 0;
> + for (i = 0; i < sizeof(*header) - 2; i++)
> + checksum += buf[i + 0x40];
> +
> + header->checksum[0] = checksum & 0xff;
> + header->checksum[1] = (checksum >> 8) & 0xff;
> +
> + crc = crc32(buf, size - sizeof(uint32_t));
> +
> + crc_idx = size - sizeof(uint32_t);
> +
> + buf[crc_idx++] = crc & 0xff;
> + buf[crc_idx++] = (crc >> 8) & 0xff;
> + buf[crc_idx++] = (crc >> 16) & 0xff;
> + buf[crc_idx++] = (crc >> 24) & 0xff;
> }
>
> -static int add_socfpga_header(void *buf, int size)
> -{
> - struct socfpga_header *header = buf + 0x40;
> - uint8_t *buf_header = buf + 0x40;
> - uint32_t *crc;
> - unsigned checksum;
> - int length = size >> 2;
> - int i;
> -
> - if (size & 0x3) {
> - fprintf(stderr, "%s: size must be multiple of 4\n", __func__);
> - return -EINVAL;
> - }
> -
> - header->validation_word[0] = VALIDATION_WORD & 0xff;
> - header->validation_word[1] = (VALIDATION_WORD >> 8) & 0xff;
> - header->validation_word[2] = (VALIDATION_WORD >> 16) & 0xff;
> - header->validation_word[3] = (VALIDATION_WORD >> 24) & 0xff;
> - header->version = 0;
> - header->flags = 0;
> - header->program_length[0] = length & 0xff;
> - header->program_length[1] = (length >> 8) & 0xff;
> - header->spare[0] = 0;
> - header->spare[1] = 0;
> -
> - checksum = 0;
> - for (i = 0; i < sizeof(*header) - 2; i++)
> - checksum += buf_header[i];
> -
> - header->checksum[0] = checksum & 0xff;;
> - header->checksum[1] = (checksum >> 8) & 0xff;;
> -
> - crc = buf + size - sizeof(uint32_t);
> -
> - *crc = crc32(0xffffffff, buf, size - sizeof(uint32_t));
> - *crc ^= 0xffffffff;
> -
> - return 0;
> +static void add_socfpga_header_v1(uint8_t *buf,
> + size_t size,
> + unsigned long entry_offset) {
> + struct socfpga_header_v1 *header = (void*)(buf + 0x40);
> + uint32_t crc;
> + uint32_t crc_idx;
> + unsigned checksum;
> + int i;
> +
> + header->validation_word[0] = VALIDATION_WORD & 0xff;
> + header->validation_word[1] = (VALIDATION_WORD >> 8) & 0xff;
> + header->validation_word[2] = (VALIDATION_WORD >> 16) & 0xff;
> + header->validation_word[3] = (VALIDATION_WORD >> 24) & 0xff;
> + header->version = 1;
> + header->flags = 0;
> + header->header_length[0] = sizeof(*header) & 0xff;
> + header->header_length[1] = (sizeof(*header) >> 8) & 0xff;
> + header->program_length[0] = size & 0xff;
> + header->program_length[1] = (size >> 8) & 0xff;
> + header->program_length[2] = (size >> 16) & 0xff;
> + header->program_length[3] = (size >> 24) & 0xff;
> + header->program_offset[0] = entry_offset & 0xff;
> + header->program_offset[1] = (entry_offset >> 8) & 0xff;
> + header->program_offset[2] = (entry_offset >> 16) & 0xff;
> + header->program_offset[3] = (entry_offset >> 24) & 0xff;
> + header->spare[0] = 0;
> + header->spare[1] = 0;
> +
> + /* Header checksum */
> + checksum = 0;
> + for (i = 0; i < sizeof(*header) - 2; i++)
> + checksum += buf[i + 0x40];
> +
> + header->checksum[0] = checksum & 0xff;
> + header->checksum[1] = (checksum >> 8) & 0xff;
> +
> + crc = crc32(buf, size - sizeof(uint32_t));
> +
> + crc_idx = size - sizeof(uint32_t);
> +
> + buf[crc_idx++] = crc & 0xff;
> + buf[crc_idx++] = (crc >> 8) & 0xff;
> + buf[crc_idx++] = (crc >> 16) & 0xff;
> + buf[crc_idx++] = (crc >> 24) & 0xff;
> }
>
> -static void usage(const char *prgname)
> +static int write_all(int fd, uint8_t *buf, size_t size)
> {
> - fprintf(stderr, "usage: %s [OPTIONS] <infile>\n", prgname);
> + while (size) {
> + ssize_t written = write(fd, buf, size);
> +
> + if (written < 0) {
> + fprintf(stderr, "Error while writing: %s\n", strerror(errno));
> + return -1;
> + }
> +
> + if (written == 0) {
> + fprintf(stderr, "Error while writing: short write\n");
> + return -1;
> + }
> +
> + size -= (size_t)written;
> + buf += written;
> + }
> +
> + return 0;
> }
>
> -int main(int argc, char *argv[])
> +static uint32_t crc_table[256] = {
> + 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
> + 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
> + 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7,
> + 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
> + 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3,
> + 0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
> + 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef,
> + 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
> + 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb,
> + 0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
> + 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
> + 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
> + 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4,
> + 0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
> + 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08,
> + 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
> + 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc,
> + 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
> + 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050,
> + 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
> + 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
> + 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
> + 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1,
> + 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
> + 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5,
> + 0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
> + 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9,
> + 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
> + 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd,
> + 0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
> + 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
> + 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
> + 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2,
> + 0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
> + 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e,
> + 0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
> + 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a,
> + 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
> + 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676,
> + 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
> + 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
> + 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
> + 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
> +};
> +
> +uint32_t crc32(uint8_t *buf, size_t length)
> {
> - int opt, ret;
> - const char *outfile = NULL, *infile;
> - struct stat s;
> - void *buf;
> - int fd;
> - int min_image_size = 80;
> - int max_image_size = MAX_IMAGE_SIZE;
> - int addsize = 0, pad;
> -
> - while ((opt = getopt(argc, argv, "o:hb")) != -1) {
> - switch (opt) {
> - case 'b':
> - add_barebox_header = 1;
> - min_image_size = 0;
> - max_image_size = MAX_IMAGE_SIZE - 512;
> - addsize = 512;
> - break;
> - case 'h':
> - usage(argv[0]);
> - exit(0);
> - case 'o':
> - outfile = optarg;
> - break;
> - default:
> - exit(1);
> - }
> - }
> -
> - if (optind == argc) {
> - usage(argv[0]);
> - exit(1);
> - }
> -
> - infile = argv[optind];
> -
> - ret = stat(infile, &s);
> - if (ret) {
> - perror("stat");
> - exit(1);
> - }
> -
> - if (s.st_size < min_image_size) {
> - fprintf(stderr, "input image too small. Minimum is 80 bytes\n");
> - exit(1);
> - }
> -
> - if (s.st_size > max_image_size) {
> - fprintf(stderr, "input image too big. Maximum is %d bytes, got %ld bytes\n",
> - max_image_size, s.st_size);
> - exit(1);
> - }
> -
> - fd = open(infile, O_RDONLY);
> - if (fd < 0) {
> - perror("open infile");
> - exit(1);
> - }
> -
> - pad = s.st_size & 0x3;
> - if (pad)
> - pad = 4 - pad;
> -
> - buf = calloc(s.st_size + 4 + addsize + pad, 1);
> - if (!buf) {
> - perror("malloc");
> - exit(1);
> - }
> -
> - ret = read_full(fd, buf + addsize, s.st_size);
> - if (ret < 0) {
> - perror("read infile");
> - exit(1);
> - }
> -
> - close(fd);
> -
> - if (add_barebox_header) {
> - memcpy(buf, bb_header, sizeof(bb_header));
> - }
> -
> - ret = add_socfpga_header(buf, s.st_size + 4 + addsize + pad);
> - if (ret)
> - exit(1);
> -
> - fd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, 0644);
> - if (fd < 0) {
> - perror("open outfile");
> - exit(1);
> - }
> -
> - ret = write_full(fd, buf, s.st_size + 4 + addsize + pad);
> - if (ret < 0) {
> - perror("write outfile");
> - exit(1);
> - }
> -
> - exit(0);
> + uint32_t crc = 0xffffffff;
> +
> + while (length--) {
> + crc = crc << 8 ^ crc_table[(crc >> 24 ^ *(buf++)) & 0xff];
> + }
> +
> + return crc ^ 0xffffffff;
> }
> diff --git a/package/mkpimage/mkpimage.mk b/package/mkpimage/mkpimage.mk
> index c30a6809c..0236062b6 100644
> --- a/package/mkpimage/mkpimage.mk
> +++ b/package/mkpimage/mkpimage.mk
> @@ -4,9 +4,6 @@
> #
> ################################################################################
>
> -# source included in the package
> -# came from barebox's repository:
> -# http://git.pengutronix.de/?p=barebox.git;a=blob;f=scripts/socfpga_mkimage.c;h=1a7a66d98841e9f52c3ea49c651286aa1412c9a5;hb=HEAD
> HOST_MKPIMAGE_LICENSE = GPLv2
>
> define HOST_MKPIMAGE_BUILD_CMDS
> --
> 2.11.0
>
--
Lionel Flandrin
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://lists.busybox.net/pipermail/buildroot/attachments/20170126/c0b1957d/attachment-0002.asc>
More information about the buildroot
mailing list