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