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