Merge git://www.denx.de/git/u-boot-marvell
[oweals/u-boot.git] / tools / kwbimage.c
1 /*
2  * Image manipulator for Marvell SoCs
3  *  supports Kirkwood, Dove, Armada 370, and Armada XP
4  *
5  * (C) Copyright 2013 Thomas Petazzoni
6  * <thomas.petazzoni@free-electrons.com>
7  *
8  * SPDX-License-Identifier:     GPL-2.0+
9  *
10  * Not implemented: support for the register headers and secure
11  * headers in v1 images
12  */
13
14 #include "imagetool.h"
15 #include <limits.h>
16 #include <image.h>
17 #include <stdint.h>
18 #include "kwbimage.h"
19
20 static struct image_cfg_element *image_cfg;
21 static int cfgn;
22
23 struct boot_mode {
24         unsigned int id;
25         const char *name;
26 };
27
28 struct boot_mode boot_modes[] = {
29         { 0x4D, "i2c"  },
30         { 0x5A, "spi"  },
31         { 0x8B, "nand" },
32         { 0x78, "sata" },
33         { 0x9C, "pex"  },
34         { 0x69, "uart" },
35         { 0xAE, "sdio" },
36         {},
37 };
38
39 struct nand_ecc_mode {
40         unsigned int id;
41         const char *name;
42 };
43
44 struct nand_ecc_mode nand_ecc_modes[] = {
45         { 0x00, "default" },
46         { 0x01, "hamming" },
47         { 0x02, "rs" },
48         { 0x03, "disabled" },
49         {},
50 };
51
52 /* Used to identify an undefined execution or destination address */
53 #define ADDR_INVALID ((uint32_t)-1)
54
55 #define BINARY_MAX_ARGS 8
56
57 /* In-memory representation of a line of the configuration file */
58 struct image_cfg_element {
59         enum {
60                 IMAGE_CFG_VERSION = 0x1,
61                 IMAGE_CFG_BOOT_FROM,
62                 IMAGE_CFG_DEST_ADDR,
63                 IMAGE_CFG_EXEC_ADDR,
64                 IMAGE_CFG_NAND_BLKSZ,
65                 IMAGE_CFG_NAND_BADBLK_LOCATION,
66                 IMAGE_CFG_NAND_ECC_MODE,
67                 IMAGE_CFG_NAND_PAGESZ,
68                 IMAGE_CFG_BINARY,
69                 IMAGE_CFG_PAYLOAD,
70                 IMAGE_CFG_DATA,
71                 IMAGE_CFG_BAUDRATE,
72                 IMAGE_CFG_DEBUG,
73         } type;
74         union {
75                 unsigned int version;
76                 unsigned int bootfrom;
77                 struct {
78                         const char *file;
79                         unsigned int args[BINARY_MAX_ARGS];
80                         unsigned int nargs;
81                 } binary;
82                 const char *payload;
83                 unsigned int dstaddr;
84                 unsigned int execaddr;
85                 unsigned int nandblksz;
86                 unsigned int nandbadblklocation;
87                 unsigned int nandeccmode;
88                 unsigned int nandpagesz;
89                 struct ext_hdr_v0_reg regdata;
90                 unsigned int baudrate;
91                 unsigned int debug;
92         };
93 };
94
95 #define IMAGE_CFG_ELEMENT_MAX 256
96
97 /*
98  * Utility functions to manipulate boot mode and ecc modes (convert
99  * them back and forth between description strings and the
100  * corresponding numerical identifiers).
101  */
102
103 static const char *image_boot_mode_name(unsigned int id)
104 {
105         int i;
106         for (i = 0; boot_modes[i].name; i++)
107                 if (boot_modes[i].id == id)
108                         return boot_modes[i].name;
109         return NULL;
110 }
111
112 int image_boot_mode_id(const char *boot_mode_name)
113 {
114         int i;
115         for (i = 0; boot_modes[i].name; i++)
116                 if (!strcmp(boot_modes[i].name, boot_mode_name))
117                         return boot_modes[i].id;
118
119         return -1;
120 }
121
122 int image_nand_ecc_mode_id(const char *nand_ecc_mode_name)
123 {
124         int i;
125         for (i = 0; nand_ecc_modes[i].name; i++)
126                 if (!strcmp(nand_ecc_modes[i].name, nand_ecc_mode_name))
127                         return nand_ecc_modes[i].id;
128         return -1;
129 }
130
131 static struct image_cfg_element *
132 image_find_option(unsigned int optiontype)
133 {
134         int i;
135
136         for (i = 0; i < cfgn; i++) {
137                 if (image_cfg[i].type == optiontype)
138                         return &image_cfg[i];
139         }
140
141         return NULL;
142 }
143
144 static unsigned int
145 image_count_options(unsigned int optiontype)
146 {
147         int i;
148         unsigned int count = 0;
149
150         for (i = 0; i < cfgn; i++)
151                 if (image_cfg[i].type == optiontype)
152                         count++;
153
154         return count;
155 }
156
157 /*
158  * Compute a 8-bit checksum of a memory area. This algorithm follows
159  * the requirements of the Marvell SoC BootROM specifications.
160  */
161 static uint8_t image_checksum8(void *start, uint32_t len)
162 {
163         uint8_t csum = 0;
164         uint8_t *p = start;
165
166         /* check len and return zero checksum if invalid */
167         if (!len)
168                 return 0;
169
170         do {
171                 csum += *p;
172                 p++;
173         } while (--len);
174
175         return csum;
176 }
177
178 static uint32_t image_checksum32(void *start, uint32_t len)
179 {
180         uint32_t csum = 0;
181         uint32_t *p = start;
182
183         /* check len and return zero checksum if invalid */
184         if (!len)
185                 return 0;
186
187         if (len % sizeof(uint32_t)) {
188                 fprintf(stderr, "Length %d is not in multiple of %zu\n",
189                         len, sizeof(uint32_t));
190                 return 0;
191         }
192
193         do {
194                 csum += *p;
195                 p++;
196                 len -= sizeof(uint32_t);
197         } while (len > 0);
198
199         return csum;
200 }
201
202 static uint8_t baudrate_to_option(unsigned int baudrate)
203 {
204         switch (baudrate) {
205         case 2400:
206                 return MAIN_HDR_V1_OPT_BAUD_2400;
207         case 4800:
208                 return MAIN_HDR_V1_OPT_BAUD_4800;
209         case 9600:
210                 return MAIN_HDR_V1_OPT_BAUD_9600;
211         case 19200:
212                 return MAIN_HDR_V1_OPT_BAUD_19200;
213         case 38400:
214                 return MAIN_HDR_V1_OPT_BAUD_38400;
215         case 57600:
216                 return MAIN_HDR_V1_OPT_BAUD_57600;
217         case 115200:
218                 return MAIN_HDR_V1_OPT_BAUD_115200;
219         default:
220                 return MAIN_HDR_V1_OPT_BAUD_DEFAULT;
221         }
222 }
223
224 static void *image_create_v0(size_t *imagesz, struct image_tool_params *params,
225                              int payloadsz)
226 {
227         struct image_cfg_element *e;
228         size_t headersz;
229         struct main_hdr_v0 *main_hdr;
230         struct ext_hdr_v0 *ext_hdr;
231         void *image;
232         int has_ext = 0;
233
234         /*
235          * Calculate the size of the header and the size of the
236          * payload
237          */
238         headersz  = sizeof(struct main_hdr_v0);
239
240         if (image_count_options(IMAGE_CFG_DATA) > 0) {
241                 has_ext = 1;
242                 headersz += sizeof(struct ext_hdr_v0);
243         }
244
245         if (image_count_options(IMAGE_CFG_PAYLOAD) > 1) {
246                 fprintf(stderr, "More than one payload, not possible\n");
247                 return NULL;
248         }
249
250         image = malloc(headersz);
251         if (!image) {
252                 fprintf(stderr, "Cannot allocate memory for image\n");
253                 return NULL;
254         }
255
256         memset(image, 0, headersz);
257
258         main_hdr = image;
259
260         /* Fill in the main header */
261         main_hdr->blocksize =
262                 cpu_to_le32(payloadsz + sizeof(uint32_t) - headersz);
263         main_hdr->srcaddr   = cpu_to_le32(headersz);
264         main_hdr->ext       = has_ext;
265         main_hdr->destaddr  = cpu_to_le32(params->addr);
266         main_hdr->execaddr  = cpu_to_le32(params->ep);
267
268         e = image_find_option(IMAGE_CFG_BOOT_FROM);
269         if (e)
270                 main_hdr->blockid = e->bootfrom;
271         e = image_find_option(IMAGE_CFG_NAND_ECC_MODE);
272         if (e)
273                 main_hdr->nandeccmode = e->nandeccmode;
274         e = image_find_option(IMAGE_CFG_NAND_PAGESZ);
275         if (e)
276                 main_hdr->nandpagesize = cpu_to_le16(e->nandpagesz);
277         main_hdr->checksum = image_checksum8(image,
278                                              sizeof(struct main_hdr_v0));
279
280         /* Generate the ext header */
281         if (has_ext) {
282                 int cfgi, datai;
283
284                 ext_hdr = image + sizeof(struct main_hdr_v0);
285                 ext_hdr->offset = cpu_to_le32(0x40);
286
287                 for (cfgi = 0, datai = 0; cfgi < cfgn; cfgi++) {
288                         e = &image_cfg[cfgi];
289                         if (e->type != IMAGE_CFG_DATA)
290                                 continue;
291
292                         ext_hdr->rcfg[datai].raddr =
293                                 cpu_to_le32(e->regdata.raddr);
294                         ext_hdr->rcfg[datai].rdata =
295                                 cpu_to_le32(e->regdata.rdata);
296                         datai++;
297                 }
298
299                 ext_hdr->checksum = image_checksum8(ext_hdr,
300                                                     sizeof(struct ext_hdr_v0));
301         }
302
303         *imagesz = headersz;
304         return image;
305 }
306
307 static size_t image_headersz_v1(struct image_tool_params *params,
308                                 int *hasext)
309 {
310         struct image_cfg_element *binarye;
311         size_t headersz;
312         int ret;
313
314         /*
315          * Calculate the size of the header and the size of the
316          * payload
317          */
318         headersz = sizeof(struct main_hdr_v1);
319
320         if (image_count_options(IMAGE_CFG_BINARY) > 1) {
321                 fprintf(stderr, "More than one binary blob, not supported\n");
322                 return 0;
323         }
324
325         if (image_count_options(IMAGE_CFG_PAYLOAD) > 1) {
326                 fprintf(stderr, "More than one payload, not possible\n");
327                 return 0;
328         }
329
330         binarye = image_find_option(IMAGE_CFG_BINARY);
331         if (binarye) {
332                 struct stat s;
333
334                 ret = stat(binarye->binary.file, &s);
335                 if (ret < 0) {
336                         char cwd[PATH_MAX];
337                         char *dir = cwd;
338
339                         memset(cwd, 0, sizeof(cwd));
340                         if (!getcwd(cwd, sizeof(cwd))) {
341                                 dir = "current working directory";
342                                 perror("getcwd() failed");
343                         }
344
345                         fprintf(stderr,
346                                 "Didn't find the file '%s' in '%s' which is mandatory to generate the image\n"
347                                 "This file generally contains the DDR3 training code, and should be extracted from an existing bootable\n"
348                                 "image for your board. See 'kwbimage -x' to extract it from an existing image.\n",
349                                 binarye->binary.file, dir);
350                         return 0;
351                 }
352
353                 headersz += sizeof(struct opt_hdr_v1) +
354                         s.st_size +
355                         (binarye->binary.nargs + 2) * sizeof(uint32_t);
356                 if (hasext)
357                         *hasext = 1;
358         }
359
360 #if defined(CONFIG_SYS_U_BOOT_OFFS)
361         if (headersz > CONFIG_SYS_U_BOOT_OFFS) {
362                 fprintf(stderr, "Error: Image header (incl. SPL image) too big!\n");
363                 fprintf(stderr, "header=0x%x CONFIG_SYS_U_BOOT_OFFS=0x%x!\n",
364                         (int)headersz, CONFIG_SYS_U_BOOT_OFFS);
365                 fprintf(stderr, "Increase CONFIG_SYS_U_BOOT_OFFS!\n");
366                 return 0;
367         } else {
368                 headersz = CONFIG_SYS_U_BOOT_OFFS;
369         }
370 #endif
371
372         /*
373          * The payload should be aligned on some reasonable
374          * boundary
375          */
376         return ALIGN_SUP(headersz, 4096);
377 }
378
379 static void *image_create_v1(size_t *imagesz, struct image_tool_params *params,
380                              int payloadsz)
381 {
382         struct image_cfg_element *e, *binarye;
383         struct main_hdr_v1 *main_hdr;
384         size_t headersz;
385         void *image, *cur;
386         int hasext = 0;
387         int ret;
388
389         /*
390          * Calculate the size of the header and the size of the
391          * payload
392          */
393         headersz = image_headersz_v1(params, &hasext);
394         if (headersz == 0)
395                 return NULL;
396
397         image = malloc(headersz);
398         if (!image) {
399                 fprintf(stderr, "Cannot allocate memory for image\n");
400                 return NULL;
401         }
402
403         memset(image, 0, headersz);
404
405         cur = main_hdr = image;
406         cur += sizeof(struct main_hdr_v1);
407
408         /* Fill the main header */
409         main_hdr->blocksize    =
410                 cpu_to_le32(payloadsz - headersz + sizeof(uint32_t));
411         main_hdr->headersz_lsb = cpu_to_le16(headersz & 0xFFFF);
412         main_hdr->headersz_msb = (headersz & 0xFFFF0000) >> 16;
413         main_hdr->destaddr     = cpu_to_le32(params->addr);
414         main_hdr->execaddr     = cpu_to_le32(params->ep);
415         main_hdr->srcaddr      = cpu_to_le32(headersz);
416         main_hdr->ext          = hasext;
417         main_hdr->version      = 1;
418         e = image_find_option(IMAGE_CFG_BOOT_FROM);
419         if (e)
420                 main_hdr->blockid = e->bootfrom;
421         e = image_find_option(IMAGE_CFG_NAND_BLKSZ);
422         if (e)
423                 main_hdr->nandblocksize = e->nandblksz / (64 * 1024);
424         e = image_find_option(IMAGE_CFG_NAND_BADBLK_LOCATION);
425         if (e)
426                 main_hdr->nandbadblklocation = e->nandbadblklocation;
427         e = image_find_option(IMAGE_CFG_BAUDRATE);
428         if (e)
429                 main_hdr->options = baudrate_to_option(e->baudrate);
430         e = image_find_option(IMAGE_CFG_DEBUG);
431         if (e)
432                 main_hdr->flags = e->debug ? 0x1 : 0;
433
434         binarye = image_find_option(IMAGE_CFG_BINARY);
435         if (binarye) {
436                 struct opt_hdr_v1 *hdr = cur;
437                 uint32_t *args;
438                 size_t binhdrsz;
439                 struct stat s;
440                 int argi;
441                 FILE *bin;
442
443                 hdr->headertype = OPT_HDR_V1_BINARY_TYPE;
444
445                 bin = fopen(binarye->binary.file, "r");
446                 if (!bin) {
447                         fprintf(stderr, "Cannot open binary file %s\n",
448                                 binarye->binary.file);
449                         return NULL;
450                 }
451
452                 fstat(fileno(bin), &s);
453
454                 binhdrsz = sizeof(struct opt_hdr_v1) +
455                         (binarye->binary.nargs + 2) * sizeof(uint32_t) +
456                         s.st_size;
457
458                 /*
459                  * The size includes the binary image size, rounded
460                  * up to a 4-byte boundary. Plus 4 bytes for the
461                  * next-header byte and 3-byte alignment at the end.
462                  */
463                 binhdrsz = ALIGN_SUP(binhdrsz, 4) + 4;
464                 hdr->headersz_lsb = cpu_to_le16(binhdrsz & 0xFFFF);
465                 hdr->headersz_msb = (binhdrsz & 0xFFFF0000) >> 16;
466
467                 cur += sizeof(struct opt_hdr_v1);
468
469                 args = cur;
470                 *args = cpu_to_le32(binarye->binary.nargs);
471                 args++;
472                 for (argi = 0; argi < binarye->binary.nargs; argi++)
473                         args[argi] = cpu_to_le32(binarye->binary.args[argi]);
474
475                 cur += (binarye->binary.nargs + 1) * sizeof(uint32_t);
476
477                 ret = fread(cur, s.st_size, 1, bin);
478                 if (ret != 1) {
479                         fprintf(stderr,
480                                 "Could not read binary image %s\n",
481                                 binarye->binary.file);
482                         return NULL;
483                 }
484
485                 fclose(bin);
486
487                 cur += ALIGN_SUP(s.st_size, 4);
488
489                 /*
490                  * For now, we don't support more than one binary
491                  * header, and no other header types are
492                  * supported. So, the binary header is necessarily the
493                  * last one
494                  */
495                 *((uint32_t *)cur) = 0x00000000;
496
497                 cur += sizeof(uint32_t);
498         }
499
500         /* Calculate and set the header checksum */
501         main_hdr->checksum = image_checksum8(main_hdr, headersz);
502
503         *imagesz = headersz;
504         return image;
505 }
506
507 static int image_create_config_parse_oneline(char *line,
508                                              struct image_cfg_element *el)
509 {
510         char *keyword, *saveptr;
511         char deliminiters[] = " \t";
512
513         keyword = strtok_r(line, deliminiters, &saveptr);
514         if (!strcmp(keyword, "VERSION")) {
515                 char *value = strtok_r(NULL, deliminiters, &saveptr);
516                 el->type = IMAGE_CFG_VERSION;
517                 el->version = atoi(value);
518         } else if (!strcmp(keyword, "BOOT_FROM")) {
519                 char *value = strtok_r(NULL, deliminiters, &saveptr);
520                 int ret = image_boot_mode_id(value);
521                 if (ret < 0) {
522                         fprintf(stderr,
523                                 "Invalid boot media '%s'\n", value);
524                         return -1;
525                 }
526                 el->type = IMAGE_CFG_BOOT_FROM;
527                 el->bootfrom = ret;
528         } else if (!strcmp(keyword, "NAND_BLKSZ")) {
529                 char *value = strtok_r(NULL, deliminiters, &saveptr);
530                 el->type = IMAGE_CFG_NAND_BLKSZ;
531                 el->nandblksz = strtoul(value, NULL, 16);
532         } else if (!strcmp(keyword, "NAND_BADBLK_LOCATION")) {
533                 char *value = strtok_r(NULL, deliminiters, &saveptr);
534                 el->type = IMAGE_CFG_NAND_BADBLK_LOCATION;
535                 el->nandbadblklocation =
536                         strtoul(value, NULL, 16);
537         } else if (!strcmp(keyword, "NAND_ECC_MODE")) {
538                 char *value = strtok_r(NULL, deliminiters, &saveptr);
539                 int ret = image_nand_ecc_mode_id(value);
540                 if (ret < 0) {
541                         fprintf(stderr,
542                                 "Invalid NAND ECC mode '%s'\n", value);
543                         return -1;
544                 }
545                 el->type = IMAGE_CFG_NAND_ECC_MODE;
546                 el->nandeccmode = ret;
547         } else if (!strcmp(keyword, "NAND_PAGE_SIZE")) {
548                 char *value = strtok_r(NULL, deliminiters, &saveptr);
549                 el->type = IMAGE_CFG_NAND_PAGESZ;
550                 el->nandpagesz = strtoul(value, NULL, 16);
551         } else if (!strcmp(keyword, "BINARY")) {
552                 char *value = strtok_r(NULL, deliminiters, &saveptr);
553                 int argi = 0;
554
555                 el->type = IMAGE_CFG_BINARY;
556                 el->binary.file = strdup(value);
557                 while (1) {
558                         value = strtok_r(NULL, deliminiters, &saveptr);
559                         if (!value)
560                                 break;
561                         el->binary.args[argi] = strtoul(value, NULL, 16);
562                         argi++;
563                         if (argi >= BINARY_MAX_ARGS) {
564                                 fprintf(stderr,
565                                         "Too many argument for binary\n");
566                                 return -1;
567                         }
568                 }
569                 el->binary.nargs = argi;
570         } else if (!strcmp(keyword, "DATA")) {
571                 char *value1 = strtok_r(NULL, deliminiters, &saveptr);
572                 char *value2 = strtok_r(NULL, deliminiters, &saveptr);
573
574                 if (!value1 || !value2) {
575                         fprintf(stderr,
576                                 "Invalid number of arguments for DATA\n");
577                         return -1;
578                 }
579
580                 el->type = IMAGE_CFG_DATA;
581                 el->regdata.raddr = strtoul(value1, NULL, 16);
582                 el->regdata.rdata = strtoul(value2, NULL, 16);
583         } else if (!strcmp(keyword, "BAUDRATE")) {
584                 char *value = strtok_r(NULL, deliminiters, &saveptr);
585                 el->type = IMAGE_CFG_BAUDRATE;
586                 el->baudrate = strtoul(value, NULL, 10);
587         } else if (!strcmp(keyword, "DEBUG")) {
588                 char *value = strtok_r(NULL, deliminiters, &saveptr);
589                 el->type = IMAGE_CFG_DEBUG;
590                 el->debug = strtoul(value, NULL, 10);
591         } else {
592                 fprintf(stderr, "Ignoring unknown line '%s'\n", line);
593         }
594
595         return 0;
596 }
597
598 /*
599  * Parse the configuration file 'fcfg' into the array of configuration
600  * elements 'image_cfg', and return the number of configuration
601  * elements in 'cfgn'.
602  */
603 static int image_create_config_parse(FILE *fcfg)
604 {
605         int ret;
606         int cfgi = 0;
607
608         /* Parse the configuration file */
609         while (!feof(fcfg)) {
610                 char *line;
611                 char buf[256];
612
613                 /* Read the current line */
614                 memset(buf, 0, sizeof(buf));
615                 line = fgets(buf, sizeof(buf), fcfg);
616                 if (!line)
617                         break;
618
619                 /* Ignore useless lines */
620                 if (line[0] == '\n' || line[0] == '#')
621                         continue;
622
623                 /* Strip final newline */
624                 if (line[strlen(line) - 1] == '\n')
625                         line[strlen(line) - 1] = 0;
626
627                 /* Parse the current line */
628                 ret = image_create_config_parse_oneline(line,
629                                                         &image_cfg[cfgi]);
630                 if (ret)
631                         return ret;
632
633                 cfgi++;
634
635                 if (cfgi >= IMAGE_CFG_ELEMENT_MAX) {
636                         fprintf(stderr,
637                                 "Too many configuration elements in .cfg file\n");
638                         return -1;
639                 }
640         }
641
642         cfgn = cfgi;
643         return 0;
644 }
645
646 static int image_get_version(void)
647 {
648         struct image_cfg_element *e;
649
650         e = image_find_option(IMAGE_CFG_VERSION);
651         if (!e)
652                 return -1;
653
654         return e->version;
655 }
656
657 static int image_version_file(const char *input)
658 {
659         FILE *fcfg;
660         int version;
661         int ret;
662
663         fcfg = fopen(input, "r");
664         if (!fcfg) {
665                 fprintf(stderr, "Could not open input file %s\n", input);
666                 return -1;
667         }
668
669         image_cfg = malloc(IMAGE_CFG_ELEMENT_MAX *
670                            sizeof(struct image_cfg_element));
671         if (!image_cfg) {
672                 fprintf(stderr, "Cannot allocate memory\n");
673                 fclose(fcfg);
674                 return -1;
675         }
676
677         memset(image_cfg, 0,
678                IMAGE_CFG_ELEMENT_MAX * sizeof(struct image_cfg_element));
679         rewind(fcfg);
680
681         ret = image_create_config_parse(fcfg);
682         fclose(fcfg);
683         if (ret) {
684                 free(image_cfg);
685                 return -1;
686         }
687
688         version = image_get_version();
689         /* Fallback to version 0 is no version is provided in the cfg file */
690         if (version == -1)
691                 version = 0;
692
693         free(image_cfg);
694
695         return version;
696 }
697
698 static void kwbimage_set_header(void *ptr, struct stat *sbuf, int ifd,
699                                 struct image_tool_params *params)
700 {
701         FILE *fcfg;
702         void *image = NULL;
703         int version;
704         size_t headersz = 0;
705         uint32_t checksum;
706         int ret;
707         int size;
708
709         fcfg = fopen(params->imagename, "r");
710         if (!fcfg) {
711                 fprintf(stderr, "Could not open input file %s\n",
712                         params->imagename);
713                 exit(EXIT_FAILURE);
714         }
715
716         image_cfg = malloc(IMAGE_CFG_ELEMENT_MAX *
717                            sizeof(struct image_cfg_element));
718         if (!image_cfg) {
719                 fprintf(stderr, "Cannot allocate memory\n");
720                 fclose(fcfg);
721                 exit(EXIT_FAILURE);
722         }
723
724         memset(image_cfg, 0,
725                IMAGE_CFG_ELEMENT_MAX * sizeof(struct image_cfg_element));
726         rewind(fcfg);
727
728         ret = image_create_config_parse(fcfg);
729         fclose(fcfg);
730         if (ret) {
731                 free(image_cfg);
732                 exit(EXIT_FAILURE);
733         }
734
735         /* The MVEBU BootROM does not allow non word aligned payloads */
736         sbuf->st_size = ALIGN_SUP(sbuf->st_size, 4);
737
738         version = image_get_version();
739         switch (version) {
740                 /*
741                  * Fallback to version 0 if no version is provided in the
742                  * cfg file
743                  */
744         case -1:
745         case 0:
746                 image = image_create_v0(&headersz, params, sbuf->st_size);
747                 break;
748
749         case 1:
750                 image = image_create_v1(&headersz, params, sbuf->st_size);
751                 break;
752
753         default:
754                 fprintf(stderr, "Unsupported version %d\n", version);
755                 free(image_cfg);
756                 exit(EXIT_FAILURE);
757         }
758
759         if (!image) {
760                 fprintf(stderr, "Could not create image\n");
761                 free(image_cfg);
762                 exit(EXIT_FAILURE);
763         }
764
765         free(image_cfg);
766
767         /* Build and add image checksum header */
768         checksum =
769                 cpu_to_le32(image_checksum32((uint32_t *)ptr, sbuf->st_size));
770         size = write(ifd, &checksum, sizeof(uint32_t));
771         if (size != sizeof(uint32_t)) {
772                 fprintf(stderr, "Error:%s - Checksum write %d bytes %s\n",
773                         params->cmdname, size, params->imagefile);
774                 exit(EXIT_FAILURE);
775         }
776
777         sbuf->st_size += sizeof(uint32_t);
778
779         /* Finally copy the header into the image area */
780         memcpy(ptr, image, headersz);
781
782         free(image);
783 }
784
785 static void kwbimage_print_header(const void *ptr)
786 {
787         struct main_hdr_v0 *mhdr = (struct main_hdr_v0 *)ptr;
788
789         printf("Image Type:   MVEBU Boot from %s Image\n",
790                image_boot_mode_name(mhdr->blockid));
791         printf("Image version:%d\n", image_version((void *)ptr));
792         printf("Data Size:    ");
793         genimg_print_size(mhdr->blocksize - sizeof(uint32_t));
794         printf("Load Address: %08x\n", mhdr->destaddr);
795         printf("Entry Point:  %08x\n", mhdr->execaddr);
796 }
797
798 static int kwbimage_check_image_types(uint8_t type)
799 {
800         if (type == IH_TYPE_KWBIMAGE)
801                 return EXIT_SUCCESS;
802         else
803                 return EXIT_FAILURE;
804 }
805
806 static int kwbimage_verify_header(unsigned char *ptr, int image_size,
807                                   struct image_tool_params *params)
808 {
809         struct main_hdr_v0 *main_hdr;
810         struct ext_hdr_v0 *ext_hdr;
811         uint8_t checksum;
812
813         main_hdr = (void *)ptr;
814         checksum = image_checksum8(ptr,
815                                    sizeof(struct main_hdr_v0)
816                                    - sizeof(uint8_t));
817         if (checksum != main_hdr->checksum)
818                 return -FDT_ERR_BADSTRUCTURE;
819
820         /* Only version 0 extended header has checksum */
821         if (image_version((void *)ptr) == 0) {
822                 ext_hdr = (void *)ptr + sizeof(struct main_hdr_v0);
823                 checksum = image_checksum8(ext_hdr,
824                                            sizeof(struct ext_hdr_v0)
825                                            - sizeof(uint8_t));
826                 if (checksum != ext_hdr->checksum)
827                         return -FDT_ERR_BADSTRUCTURE;
828         }
829
830         return 0;
831 }
832
833 static int kwbimage_generate(struct image_tool_params *params,
834                              struct image_type_params *tparams)
835 {
836         int alloc_len;
837         void *hdr;
838         int version = 0;
839
840         version = image_version_file(params->imagename);
841         if (version == 0) {
842                 alloc_len = sizeof(struct main_hdr_v0) +
843                         sizeof(struct ext_hdr_v0);
844         } else {
845                 alloc_len = image_headersz_v1(params, NULL);
846         }
847
848         hdr = malloc(alloc_len);
849         if (!hdr) {
850                 fprintf(stderr, "%s: malloc return failure: %s\n",
851                         params->cmdname, strerror(errno));
852                 exit(EXIT_FAILURE);
853         }
854
855         memset(hdr, 0, alloc_len);
856         tparams->header_size = alloc_len;
857         tparams->hdr = hdr;
858
859         /*
860          * The resulting image needs to be 4-byte aligned. At least
861          * the Marvell hdrparser tool complains if its unaligned.
862          * By returning 1 here in this function, called via
863          * tparams->vrec_header() in mkimage.c, mkimage will
864          * automatically pad the the resulting image to a 4-byte
865          * size if necessary.
866          */
867         return 1;
868 }
869
870 /*
871  * Report Error if xflag is set in addition to default
872  */
873 static int kwbimage_check_params(struct image_tool_params *params)
874 {
875         if (!strlen(params->imagename)) {
876                 fprintf(stderr, "Error:%s - Configuration file not specified, "
877                         "it is needed for kwbimage generation\n",
878                         params->cmdname);
879                 return CFG_INVALID;
880         }
881
882         return (params->dflag && (params->fflag || params->lflag)) ||
883                 (params->fflag && (params->dflag || params->lflag)) ||
884                 (params->lflag && (params->dflag || params->fflag)) ||
885                 (params->xflag) || !(strlen(params->imagename));
886 }
887
888 /*
889  * kwbimage type parameters definition
890  */
891 U_BOOT_IMAGE_TYPE(
892         kwbimage,
893         "Marvell MVEBU Boot Image support",
894         0,
895         NULL,
896         kwbimage_check_params,
897         kwbimage_verify_header,
898         kwbimage_print_header,
899         kwbimage_set_header,
900         NULL,
901         kwbimage_check_image_types,
902         NULL,
903         kwbimage_generate
904 );