0e7c96a780e470dc4d2b2e482a378c69feb832cf
[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
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         struct ext_hdr_v0 *ext_hdr;
234         void *image;
235         int has_ext = 0;
236
237         /*
238          * Calculate the size of the header and the size of the
239          * payload
240          */
241         headersz  = sizeof(struct main_hdr_v0);
242
243         if (image_count_options(IMAGE_CFG_DATA) > 0) {
244                 has_ext = 1;
245                 headersz += sizeof(struct ext_hdr_v0);
246         }
247
248         if (image_count_options(IMAGE_CFG_PAYLOAD) > 1) {
249                 fprintf(stderr, "More than one payload, not possible\n");
250                 return NULL;
251         }
252
253         image = malloc(headersz);
254         if (!image) {
255                 fprintf(stderr, "Cannot allocate memory for image\n");
256                 return NULL;
257         }
258
259         memset(image, 0, headersz);
260
261         main_hdr = image;
262
263         /* Fill in the main header */
264         main_hdr->blocksize =
265                 cpu_to_le32(payloadsz + sizeof(uint32_t) - headersz);
266         main_hdr->srcaddr   = cpu_to_le32(headersz);
267         main_hdr->ext       = has_ext;
268         main_hdr->destaddr  = cpu_to_le32(params->addr);
269         main_hdr->execaddr  = cpu_to_le32(params->ep);
270
271         e = image_find_option(IMAGE_CFG_BOOT_FROM);
272         if (e)
273                 main_hdr->blockid = e->bootfrom;
274         e = image_find_option(IMAGE_CFG_NAND_ECC_MODE);
275         if (e)
276                 main_hdr->nandeccmode = e->nandeccmode;
277         e = image_find_option(IMAGE_CFG_NAND_PAGESZ);
278         if (e)
279                 main_hdr->nandpagesize = cpu_to_le16(e->nandpagesz);
280         main_hdr->checksum = image_checksum8(image,
281                                              sizeof(struct main_hdr_v0));
282
283         /* Generate the ext header */
284         if (has_ext) {
285                 int cfgi, datai;
286
287                 ext_hdr = image + sizeof(struct main_hdr_v0);
288                 ext_hdr->offset = cpu_to_le32(0x40);
289
290                 for (cfgi = 0, datai = 0; cfgi < cfgn; cfgi++) {
291                         e = &image_cfg[cfgi];
292                         if (e->type != IMAGE_CFG_DATA)
293                                 continue;
294
295                         ext_hdr->rcfg[datai].raddr =
296                                 cpu_to_le32(e->regdata.raddr);
297                         ext_hdr->rcfg[datai].rdata =
298                                 cpu_to_le32(e->regdata.rdata);
299                         datai++;
300                 }
301
302                 ext_hdr->checksum = image_checksum8(ext_hdr,
303                                                     sizeof(struct ext_hdr_v0));
304         }
305
306         *imagesz = headersz;
307         return image;
308 }
309
310 static size_t image_headersz_v1(struct image_tool_params *params,
311                                 int *hasext)
312 {
313         struct image_cfg_element *binarye;
314         size_t headersz;
315         int ret;
316
317         /*
318          * Calculate the size of the header and the size of the
319          * payload
320          */
321         headersz = sizeof(struct main_hdr_v1);
322
323         if (image_count_options(IMAGE_CFG_BINARY) > 1) {
324                 fprintf(stderr, "More than one binary blob, not supported\n");
325                 return 0;
326         }
327
328         if (image_count_options(IMAGE_CFG_PAYLOAD) > 1) {
329                 fprintf(stderr, "More than one payload, not possible\n");
330                 return 0;
331         }
332
333         binarye = image_find_option(IMAGE_CFG_BINARY);
334         if (binarye) {
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         void *image, *cur;
389         int hasext = 0;
390         int ret;
391
392         /*
393          * Calculate the size of the header and the size of the
394          * payload
395          */
396         headersz = image_headersz_v1(params, &hasext);
397         if (headersz == 0)
398                 return NULL;
399
400         image = malloc(headersz);
401         if (!image) {
402                 fprintf(stderr, "Cannot allocate memory for image\n");
403                 return NULL;
404         }
405
406         memset(image, 0, headersz);
407
408         cur = main_hdr = image;
409         cur += sizeof(struct main_hdr_v1);
410
411         /* Fill the main header */
412         main_hdr->blocksize    =
413                 cpu_to_le32(payloadsz - headersz + sizeof(uint32_t));
414         main_hdr->headersz_lsb = cpu_to_le16(headersz & 0xFFFF);
415         main_hdr->headersz_msb = (headersz & 0xFFFF0000) >> 16;
416         main_hdr->destaddr     = cpu_to_le32(params->addr)
417                                  - sizeof(image_header_t);
418         main_hdr->execaddr     = cpu_to_le32(params->ep);
419         main_hdr->srcaddr      = cpu_to_le32(headersz);
420         main_hdr->ext          = hasext;
421         main_hdr->version      = 1;
422         e = image_find_option(IMAGE_CFG_BOOT_FROM);
423         if (e)
424                 main_hdr->blockid = e->bootfrom;
425         e = image_find_option(IMAGE_CFG_NAND_BLKSZ);
426         if (e)
427                 main_hdr->nandblocksize = e->nandblksz / (64 * 1024);
428         e = image_find_option(IMAGE_CFG_NAND_BADBLK_LOCATION);
429         if (e)
430                 main_hdr->nandbadblklocation = e->nandbadblklocation;
431         e = image_find_option(IMAGE_CFG_BAUDRATE);
432         if (e)
433                 main_hdr->options = baudrate_to_option(e->baudrate);
434         e = image_find_option(IMAGE_CFG_DEBUG);
435         if (e)
436                 main_hdr->flags = e->debug ? 0x1 : 0;
437
438         binarye = image_find_option(IMAGE_CFG_BINARY);
439         if (binarye) {
440                 struct opt_hdr_v1 *hdr = cur;
441                 uint32_t *args;
442                 size_t binhdrsz;
443                 struct stat s;
444                 int argi;
445                 FILE *bin;
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 = 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         struct ext_hdr_v0 *ext_hdr;
821         uint8_t checksum;
822
823         main_hdr = (void *)ptr;
824         checksum = image_checksum8(ptr,
825                                    sizeof(struct main_hdr_v0)
826                                    - sizeof(uint8_t));
827         if (checksum != main_hdr->checksum)
828                 return -FDT_ERR_BADSTRUCTURE;
829
830         /* Only version 0 extended header has checksum */
831         if (image_version((void *)ptr) == 0) {
832                 ext_hdr = (void *)ptr + sizeof(struct main_hdr_v0);
833                 checksum = image_checksum8(ext_hdr,
834                                            sizeof(struct ext_hdr_v0)
835                                            - sizeof(uint8_t));
836                 if (checksum != ext_hdr->checksum)
837                         return -FDT_ERR_BADSTRUCTURE;
838         }
839
840         return 0;
841 }
842
843 static int kwbimage_generate(struct image_tool_params *params,
844                              struct image_type_params *tparams)
845 {
846         int alloc_len;
847         void *hdr;
848         int version = 0;
849
850         version = image_version_file(params->imagename);
851         if (version == 0) {
852                 alloc_len = sizeof(struct main_hdr_v0) +
853                         sizeof(struct ext_hdr_v0);
854         } else {
855                 alloc_len = image_headersz_v1(params, NULL);
856         }
857
858         hdr = malloc(alloc_len);
859         if (!hdr) {
860                 fprintf(stderr, "%s: malloc return failure: %s\n",
861                         params->cmdname, strerror(errno));
862                 exit(EXIT_FAILURE);
863         }
864
865         memset(hdr, 0, alloc_len);
866         tparams->header_size = alloc_len;
867         tparams->hdr = hdr;
868
869         /*
870          * The resulting image needs to be 4-byte aligned. At least
871          * the Marvell hdrparser tool complains if its unaligned.
872          * By returning 1 here in this function, called via
873          * tparams->vrec_header() in mkimage.c, mkimage will
874          * automatically pad the the resulting image to a 4-byte
875          * size if necessary.
876          */
877         return 1;
878 }
879
880 /*
881  * Report Error if xflag is set in addition to default
882  */
883 static int kwbimage_check_params(struct image_tool_params *params)
884 {
885         if (!strlen(params->imagename)) {
886                 char *msg = "Configuration file for kwbimage creation omitted";
887
888                 fprintf(stderr, "Error:%s - %s\n", params->cmdname, msg);
889                 return CFG_INVALID;
890         }
891
892         return (params->dflag && (params->fflag || params->lflag)) ||
893                 (params->fflag && (params->dflag || params->lflag)) ||
894                 (params->lflag && (params->dflag || params->fflag)) ||
895                 (params->xflag) || !(strlen(params->imagename));
896 }
897
898 /*
899  * kwbimage type parameters definition
900  */
901 U_BOOT_IMAGE_TYPE(
902         kwbimage,
903         "Marvell MVEBU Boot Image support",
904         0,
905         NULL,
906         kwbimage_check_params,
907         kwbimage_verify_header,
908         kwbimage_print_header,
909         kwbimage_set_header,
910         NULL,
911         kwbimage_check_image_types,
912         NULL,
913         kwbimage_generate
914 );