mkpimage: rewrite to support header version 1
PATCH 1/3 mkpimage: rewrite to support header version 1
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).
--- package/mkpimage/mkpimage.c | 767 ++++++++++++++++++++++++++++--------------- package/mkpimage/mkpimage.mk | 3 - 2 files changed, 511 insertions(+), 259 deletions(-)
package/mkpimage/mkpimage.c +511 -256
@@ -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 ; }
package/mkpimage/mkpimage.mk +0 -3
@@ -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
Signature · 1 line
2.11.0
PATCH 1/3 mkpimage: rewrite to support header version 1
Quoted 201 lines · Lionel Flandrin
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 <[email protected]>--- package/mkpimage/mkpimage.c | 767 ++++++++++++++++++++++++++++--------------- package/mkpimage/mkpimage.mk | 3 - 2 files changed, 511 insertions(+), 259 deletions(-)package/mkpimage/mkpimage.c +95
-64@@ -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; - }
package/mkpimage/mkpimage.c line 121
Quoted 10 lines
package/mkpimage/mkpimage.c +8
-2- -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
Quoted 628 lines
package/mkpimage/mkpimage.c +408
-190+ {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 ; }package/mkpimage/mkpimage.mk +0
-3@@ -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_CMDSSignature · 1 line
2.11.0
Signature · 8 lines
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>
PATCH 1/3 mkpimage: rewrite to support header version 1
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).
--- package/mkpimage/mkpimage.c | 768 ++++++++++++++++++++++++++++--------------- package/mkpimage/mkpimage.mk | 3 - 2 files changed, 512 insertions(+), 259 deletions(-)
package/mkpimage/mkpimage.c +512 -256
@@ -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 ; }
package/mkpimage/mkpimage.mk +0 -3
@@ -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
Signature · 1 line
2.11.0
PATCH 1/3 mkpimage: rewrite to support header version 1
Hello,
Quoted 7 lines · Lionel Flandrin
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.
Quoted 7 lines
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 <[email protected]>
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
Signature · 3 lines
Thomas Petazzoni, CTO, Free Electrons Embedded Linux and Kernel engineering http://free-electrons.com
PATCH 1/3 mkpimage: rewrite to support header version 1
Quoted 16 lines · Thomas Petazzoni
Hello,
Quoted 13 lines · Lionel Flandrin
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).
Quoted 4 lines
Quoted 1 line
Signed-off-by Lionel Flandrin <[email protected]>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.
Quoted 1 line
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.
Quoted 3 lines
Best regards,
Thomas
Thank you for taking the time to review this,
Signature · 8 lines
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>
PATCH 1/3 mkpimage: rewrite to support header version 1
Hello,
Quoted 4 lines · Lionel Flandrin
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
Signature · 3 lines
Thomas Petazzoni, CTO, Free Electrons Embedded Linux and Kernel engineering http://free-electrons.com
PATCH 1/3 mkpimage: rewrite to support header version 1
Quoted 11 lines · Thomas Petazzoni
Hello,
Quoted 4 lines · Lionel Flandrin
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.
Quoted 6 lines
Thomas
Signature · 3 lines
Thomas Petazzoni, CTO, Free Electrons Embedded Linux and Kernel engineering http://free-electrons.com
Signature · 8 lines
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>
PATCH 1/2 mkpimage: bump to latest barebox version
Adds support for header v1 (used on Arria 10 SoCs)
--- package/mkpimage/mkpimage.c | 149 ++++++++++++++++++++++++++++++++++--------- package/mkpimage/mkpimage.mk | 6 +- 2 files changed, 122 insertions(+), 33 deletions(-)
package/mkpimage/mkpimage.c +119 -30
@@ -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 );
package/mkpimage/mkpimage.mk +3 -3
@@ -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
Signature · 1 line
2.11.0
PATCH 2/2 u-boot: Add support for Altera mkpimage generation
This image format is used by Altera's SoC FPGAs BootROMs.
--- boot/uboot/Config.in | 30 ++++++++++++++++++++++++++++++ boot/uboot/uboot.mk | 12 ++++++++++++ 2 files changed, 42 insertions(+)
boot/uboot/Config.in +30 -0
@@ -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
boot/uboot/uboot.mk +12 -0
@@ -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
Signature · 1 line
2.11.0
PATCH 2/2 u-boot: Add support for Altera mkpimage generation
Hello,
Quoted 3 lines · Lionel Flandrin
This image format is used by Altera's SoC FPGAs BootROMs.
Signed-off-by Lionel Flandrin <[email protected]>
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
Signature · 3 lines
Thomas Petazzoni, CTO, Free Electrons Embedded Linux and Kernel engineering http://free-electrons.com
PATCH 2/2 u-boot: Add support for Altera mkpimage generation
Quoted 5 lines · Thomas Petazzoni
Hello,
Quoted 2 lines · Lionel Flandrin
This image format is used by Altera's SoC FPGAs BootROMs.
Quoted 8 lines
Quoted 1 line
Signed-off-by Lionel Flandrin <[email protected]>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 theBR2_TARGET_UBOOT_ALTERA_SOCFPGA_IMAGE_CRCoption.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.
Quoted 3 lines
Thanks!
Thomas
Thank you for reviewing this,
Signature · 8 lines
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>
PATCH 2/2 u-boot: Add support for Altera mkpimage generation
Hello,
Quoted 12 lines · Lionel Flandrin
Quoted 6 lines
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 theBR2_TARGET_UBOOT_ALTERA_SOCFPGA_IMAGE_CRCoption.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.
Quoted 4 lines
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)) elseUBOOT_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))
)endefUBOOT_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
Signature · 3 lines
Thomas Petazzoni, CTO, Free Electrons Embedded Linux and Kernel engineering http://free-electrons.com
PATCH 2/2 u-boot: Add support for Altera mkpimage generation
Quoted 73 lines · Thomas Petazzoni
Hello,
Quoted 12 lines · Lionel Flandrin
Quoted 6 lines
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 theBR2_TARGET_UBOOT_ALTERA_SOCFPGA_IMAGE_CRCoption.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.
Quoted 4 lines
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_BINso select u-boot-dtb.bin as the output format.2. Adjust the
BR2_TARGET_UBOOT_ALTERA_SOCFPGA_IMAGE_CRCoption 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 onBR2_arm
depends onBR2_TARGET_UBOOT_SPL||BR2_TARGET_UBOOT_FORMAT_DTB_BINhelpPass 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_NAMEusing mkpimage ifBR2_TARGET_UBOOT_SPLis enabled. Otherwise, it will convert the full U-Boot image u-boot-dtb.bin ifBR2_TARGET_UBOOT_FORMAT_DTB_BINis 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)) elseUBOOT_CRC_ALTERA_SOCFPGA_INPUT_IMAGES= u-boot-dtb.bin
endif
defineUBOOT_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-mkpimageUBOOT_POST_INSTALL_IMAGES_HOOKS+=UBOOT_CRC_ALTERA_SOCFPGA_IMAGEendif
Quoted 4 lines
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.
Quoted 5 lines
Thomas
Signature · 3 lines
Thomas Petazzoni, CTO, Free Electrons Embedded Linux and Kernel engineering http://free-electrons.com
Signature · 8 lines
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>
PATCH 1/2 u-boot: add an option to generate u-boot-dtb.bin
In reply to Lionel Flandrin--- boot/uboot/Config.in | 3 +++ boot/uboot/uboot.mk | 5 +++++ 2 files changed, 8 insertions(+)
boot/uboot/Config.in +3 -0
@@ -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"
boot/uboot/uboot.mk +5 -0
@@ -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
Signature · 1 line
2.11.0
PATCH 2/2 u-boot: add support for full image socfpga mkpimage support
Previously only SPL packaging was supported, now we can also wrap the u-boot-dtb.bin if enabled.
--- boot/uboot/Config.in | 18 +++++++++++++++--- boot/uboot/uboot.mk | 10 +++++++++- 2 files changed, 24 insertions(+), 4 deletions(-)
boot/uboot/Config.in +15 -3
@@ -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
boot/uboot/uboot.mk +9 -1
@@ -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)) )
Signature · 1 line
2.11.0
PATCH 2/2 u-boot: add support for full image socfpga mkpimage support
Hello,
Thanks for this new iteration!
boot/uboot/uboot.mk UBOOT_POST_INSTALL_IMAGES_HOOKS += UBOOT_GENERATE_ZYNQ_IMAGE · line 271
Quoted 8 lines · Lionel Flandrin
ifeq ($(BR2_TARGET_UBOOT_ALTERA_SOCFPGA_IMAGE_CRC),y)
boot/uboot/uboot.mk +7
-0+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
Signature · 3 lines
Thomas Petazzoni, CTO, Free Electrons Embedded Linux and Kernel engineering http://free-electrons.com
PATCH 2/2 u-boot: add support for full image socfpga mkpimage support
Quoted 1 line · Thomas Petazzoni
Hello,
Hello Thomas,
Quoted 17 lines
Thanks for this new iteration!
boot/uboot/uboot.mk UBOOT_POST_INSTALL_IMAGES_HOOKS += UBOOT_GENERATE_ZYNQ_IMAGE · line 271
Quoted 8 lines · Lionel Flandrin
ifeq ($(BR2_TARGET_UBOOT_ALTERA_SOCFPGA_IMAGE_CRC),y)
boot/uboot/uboot.mk +7
-0+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 +endifSo 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 ?
Quoted 3 lines
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.
Quoted 1 line
Thomas
Signature · 8 lines
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>
PATCH 2/2 u-boot: add support for full image socfpga mkpimage support
Hello,
Quoted 32 lines · Lionel Flandrin
Quoted 17 lines
Thanks for this new iteration!
boot/uboot/uboot.mk UBOOT_POST_INSTALL_IMAGES_HOOKS += UBOOT_GENERATE_ZYNQ_IMAGE · line 271
Quoted 8 lines · Lionel Flandrin
ifeq ($(BR2_TARGET_UBOOT_ALTERA_SOCFPGA_IMAGE_CRC),y)
boot/uboot/uboot.mk +7
-0+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 +endifSo 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 ?
Quoted 3 lines
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 v1I believe the main reason for the v1 header is simply to allow file sizes greater than 64k.
Quoted 8 lines
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
Makefilewouldn'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.
Quoted 8 lines
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
Signature · 3 lines
Thomas Petazzoni, CTO, Free Electrons Embedded Linux and Kernel engineering http://free-electrons.com
PATCH v2 2/2 u-boot: add support for full image socfpga mkpimage
In reply to Lionel FlandrinPreviously only SPL packaging was supported, now we can also wrap the u-boot-dtb.bin if enabled.
---
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(-)
boot/uboot/Config.in +17 -3
@@ -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
boot/uboot/uboot.mk +9 -1
@@ -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)) )
Signature · 1 line
2.11.0
PATCH v2 2/2 u-boot: add support for full image socfpga mkpimage
Hello,
Quoted 4 lines · Lionel Flandrin
Previously only SPL packaging was supported, now we can also wrap the u-boot-dtb.bin if enabled.
Signed-off-by Lionel Flandrin <[email protected]>
I've extended the commit log quite a bit to explain what is going on.
boot/uboot/Config.in config BR2_TARGET_UBOOT_ZYNQ_IMAGE · line 365
Quoted 7 lines
boot/uboot/Config.in +7
-0+ 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
Signature · 3 lines
Thomas Petazzoni, CTO, Free Electrons Embedded Linux and Kernel engineering http://free-electrons.com
Thomas Petazzoni
AppliedPATCH 1/2 u-boot: add an option to generate u-boot-dtb.bin
In reply to Lionel FlandrinHello,
Quoted 5 lines · Lionel Flandrin
Signed-off-by Lionel Flandrin <[email protected]>--- boot/uboot/Config.in | 3 +++ boot/uboot/uboot.mk | 5 +++++ 2 files changed, 8 insertions(+)
Applied to master, thanks.
Thomas
Signature · 3 lines
Thomas Petazzoni, CTO, Free Electrons Embedded Linux, Kernel and Android engineering http://free-electrons.com
Thomas Petazzoni
AppliedPATCH 1/2 mkpimage: bump to latest barebox version
In reply to Lionel FlandrinHello,
Quoted 7 lines · Lionel Flandrin
Adds support for header v1 (used on Arria 10 SoCs)
Signed-off-by Lionel Flandrin <[email protected]>--- package/mkpimage/mkpimage.c | 149 ++++++++++++++++++++++++++++++++++--------- package/mkpimage/mkpimage.mk | 6 +- 2 files changed, 122 insertions(+), 33 deletions(-)
Applied to master, thanks.
Thomas
Signature · 3 lines
Thomas Petazzoni, CTO, Free Electrons Embedded Linux, Kernel and Android engineering http://free-electrons.com
PATCH 2/3 u-boot: Add support for Altera mkpimage generation
In reply to Lionel FlandrinThis image format is used by Altera's SoC FPGAs BootROMs.
--- boot/uboot/Config.in | 30 ++++++++++++++++++++++++++++++ boot/uboot/uboot.mk | 12 ++++++++++++ 2 files changed, 42 insertions(+)
boot/uboot/Config.in +30 -0
@@ -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
boot/uboot/uboot.mk +12 -0
@@ -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
Signature · 1 line
2.11.0
PATCH 3/3 DEVELOPERS: Add Lionel Flandrin to package/mkpimage
--- DEVELOPERS | 1 + 1 file changed, 1 insertion(+)
DEVELOPERS +1 -0
@@ -918,6 +918,7 @@ N: Lee Jones <[email protected]> F: boot/afboot-stm32/ N: Lionel Flandrin <[email protected]> +F: package/mkpimage/ F: package/python-babel/ F: package/python-flask-babel/
Signature · 1 line
2.11.0