6cd4c34271502f7e6462fc1c2a75c12ae1a16ec5
[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         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
373         headersz = CONFIG_SYS_U_BOOT_OFFS;
374 #endif
375
376         /*
377          * The payload should be aligned on some reasonable
378          * boundary
379          */
380         return ALIGN_SUP(headersz, 4096);
381 }
382
383 int add_binary_header_v1(uint8_t *cur)
384 {
385         struct image_cfg_element *binarye;
386         struct opt_hdr_v1 *hdr = (struct opt_hdr_v1 *)cur;
387         uint32_t *args;
388         size_t binhdrsz;
389         struct stat s;
390         int argi;
391         FILE *bin;
392         int ret;
393
394         binarye = image_find_option(IMAGE_CFG_BINARY);
395
396         if (!binarye)
397                 return 0;
398
399         hdr->headertype = OPT_HDR_V1_BINARY_TYPE;
400
401         bin = fopen(binarye->binary.file, "r");
402         if (!bin) {
403                 fprintf(stderr, "Cannot open binary file %s\n",
404                         binarye->binary.file);
405                 return -1;
406         }
407
408         fstat(fileno(bin), &s);
409
410         binhdrsz = sizeof(struct opt_hdr_v1) +
411                 (binarye->binary.nargs + 2) * sizeof(uint32_t) +
412                 s.st_size;
413
414         /*
415          * The size includes the binary image size, rounded
416          * up to a 4-byte boundary. Plus 4 bytes for the
417          * next-header byte and 3-byte alignment at the end.
418          */
419         binhdrsz = ALIGN_SUP(binhdrsz, 4) + 4;
420         hdr->headersz_lsb = cpu_to_le16(binhdrsz & 0xFFFF);
421         hdr->headersz_msb = (binhdrsz & 0xFFFF0000) >> 16;
422
423         cur += sizeof(struct opt_hdr_v1);
424
425         args = (uint32_t *)cur;
426         *args = cpu_to_le32(binarye->binary.nargs);
427         args++;
428         for (argi = 0; argi < binarye->binary.nargs; argi++)
429                 args[argi] = cpu_to_le32(binarye->binary.args[argi]);
430
431         cur += (binarye->binary.nargs + 1) * sizeof(uint32_t);
432
433         ret = fread(cur, s.st_size, 1, bin);
434         if (ret != 1) {
435                 fprintf(stderr,
436                         "Could not read binary image %s\n",
437                         binarye->binary.file);
438                 return -1;
439         }
440
441         fclose(bin);
442
443         cur += ALIGN_SUP(s.st_size, 4);
444
445         /*
446          * For now, we don't support more than one binary
447          * header, and no other header types are
448          * supported. So, the binary header is necessarily the
449          * last one
450          */
451         *((uint32_t *)cur) = 0x00000000;
452
453         cur += sizeof(uint32_t);
454
455         return 0;
456 }
457
458 static void *image_create_v1(size_t *imagesz, struct image_tool_params *params,
459                              int payloadsz)
460 {
461         struct image_cfg_element *e;
462         struct main_hdr_v1 *main_hdr;
463         size_t headersz;
464         uint8_t *image, *cur;
465         int hasext = 0;
466
467         /*
468          * Calculate the size of the header and the size of the
469          * payload
470          */
471         headersz = image_headersz_v1(&hasext);
472         if (headersz == 0)
473                 return NULL;
474
475         image = malloc(headersz);
476         if (!image) {
477                 fprintf(stderr, "Cannot allocate memory for image\n");
478                 return NULL;
479         }
480
481         memset(image, 0, headersz);
482
483         main_hdr = (struct main_hdr_v1 *)image;
484         cur = image + sizeof(struct main_hdr_v1);
485
486         /* Fill the main header */
487         main_hdr->blocksize    =
488                 cpu_to_le32(payloadsz - headersz + sizeof(uint32_t));
489         main_hdr->headersz_lsb = cpu_to_le16(headersz & 0xFFFF);
490         main_hdr->headersz_msb = (headersz & 0xFFFF0000) >> 16;
491         main_hdr->destaddr     = cpu_to_le32(params->addr)
492                                  - sizeof(image_header_t);
493         main_hdr->execaddr     = cpu_to_le32(params->ep);
494         main_hdr->srcaddr      = cpu_to_le32(headersz);
495         main_hdr->ext          = hasext;
496         main_hdr->version      = 1;
497         e = image_find_option(IMAGE_CFG_BOOT_FROM);
498         if (e)
499                 main_hdr->blockid = e->bootfrom;
500         e = image_find_option(IMAGE_CFG_NAND_BLKSZ);
501         if (e)
502                 main_hdr->nandblocksize = e->nandblksz / (64 * 1024);
503         e = image_find_option(IMAGE_CFG_NAND_BADBLK_LOCATION);
504         if (e)
505                 main_hdr->nandbadblklocation = e->nandbadblklocation;
506         e = image_find_option(IMAGE_CFG_BAUDRATE);
507         if (e)
508                 main_hdr->options = baudrate_to_option(e->baudrate);
509         e = image_find_option(IMAGE_CFG_DEBUG);
510         if (e)
511                 main_hdr->flags = e->debug ? 0x1 : 0;
512
513         if (add_binary_header_v1(cur))
514                 return NULL;
515
516         /* Calculate and set the header checksum */
517         main_hdr->checksum = image_checksum8(main_hdr, headersz);
518
519         *imagesz = headersz;
520         return image;
521 }
522
523 static int image_create_config_parse_oneline(char *line,
524                                              struct image_cfg_element *el)
525 {
526         char *keyword, *saveptr;
527         char deliminiters[] = " \t";
528
529         keyword = strtok_r(line, deliminiters, &saveptr);
530         if (!strcmp(keyword, "VERSION")) {
531                 char *value = strtok_r(NULL, deliminiters, &saveptr);
532
533                 el->type = IMAGE_CFG_VERSION;
534                 el->version = atoi(value);
535         } else if (!strcmp(keyword, "BOOT_FROM")) {
536                 char *value = strtok_r(NULL, deliminiters, &saveptr);
537                 int ret = image_boot_mode_id(value);
538
539                 if (ret < 0) {
540                         fprintf(stderr,
541                                 "Invalid boot media '%s'\n", value);
542                         return -1;
543                 }
544                 el->type = IMAGE_CFG_BOOT_FROM;
545                 el->bootfrom = ret;
546         } else if (!strcmp(keyword, "NAND_BLKSZ")) {
547                 char *value = strtok_r(NULL, deliminiters, &saveptr);
548
549                 el->type = IMAGE_CFG_NAND_BLKSZ;
550                 el->nandblksz = strtoul(value, NULL, 16);
551         } else if (!strcmp(keyword, "NAND_BADBLK_LOCATION")) {
552                 char *value = strtok_r(NULL, deliminiters, &saveptr);
553
554                 el->type = IMAGE_CFG_NAND_BADBLK_LOCATION;
555                 el->nandbadblklocation =
556                         strtoul(value, NULL, 16);
557         } else if (!strcmp(keyword, "NAND_ECC_MODE")) {
558                 char *value = strtok_r(NULL, deliminiters, &saveptr);
559                 int ret = image_nand_ecc_mode_id(value);
560
561                 if (ret < 0) {
562                         fprintf(stderr,
563                                 "Invalid NAND ECC mode '%s'\n", value);
564                         return -1;
565                 }
566                 el->type = IMAGE_CFG_NAND_ECC_MODE;
567                 el->nandeccmode = ret;
568         } else if (!strcmp(keyword, "NAND_PAGE_SIZE")) {
569                 char *value = strtok_r(NULL, deliminiters, &saveptr);
570
571                 el->type = IMAGE_CFG_NAND_PAGESZ;
572                 el->nandpagesz = strtoul(value, NULL, 16);
573         } else if (!strcmp(keyword, "BINARY")) {
574                 char *value = strtok_r(NULL, deliminiters, &saveptr);
575                 int argi = 0;
576
577                 el->type = IMAGE_CFG_BINARY;
578                 el->binary.file = strdup(value);
579                 while (1) {
580                         value = strtok_r(NULL, deliminiters, &saveptr);
581                         if (!value)
582                                 break;
583                         el->binary.args[argi] = strtoul(value, NULL, 16);
584                         argi++;
585                         if (argi >= BINARY_MAX_ARGS) {
586                                 fprintf(stderr,
587                                         "Too many argument for binary\n");
588                                 return -1;
589                         }
590                 }
591                 el->binary.nargs = argi;
592         } else if (!strcmp(keyword, "DATA")) {
593                 char *value1 = strtok_r(NULL, deliminiters, &saveptr);
594                 char *value2 = strtok_r(NULL, deliminiters, &saveptr);
595
596                 if (!value1 || !value2) {
597                         fprintf(stderr,
598                                 "Invalid number of arguments for DATA\n");
599                         return -1;
600                 }
601
602                 el->type = IMAGE_CFG_DATA;
603                 el->regdata.raddr = strtoul(value1, NULL, 16);
604                 el->regdata.rdata = strtoul(value2, NULL, 16);
605         } else if (!strcmp(keyword, "BAUDRATE")) {
606                 char *value = strtok_r(NULL, deliminiters, &saveptr);
607                 el->type = IMAGE_CFG_BAUDRATE;
608                 el->baudrate = strtoul(value, NULL, 10);
609         } else if (!strcmp(keyword, "DEBUG")) {
610                 char *value = strtok_r(NULL, deliminiters, &saveptr);
611                 el->type = IMAGE_CFG_DEBUG;
612                 el->debug = strtoul(value, NULL, 10);
613         } else {
614                 fprintf(stderr, "Ignoring unknown line '%s'\n", line);
615         }
616
617         return 0;
618 }
619
620 /*
621  * Parse the configuration file 'fcfg' into the array of configuration
622  * elements 'image_cfg', and return the number of configuration
623  * elements in 'cfgn'.
624  */
625 static int image_create_config_parse(FILE *fcfg)
626 {
627         int ret;
628         int cfgi = 0;
629
630         /* Parse the configuration file */
631         while (!feof(fcfg)) {
632                 char *line;
633                 char buf[256];
634
635                 /* Read the current line */
636                 memset(buf, 0, sizeof(buf));
637                 line = fgets(buf, sizeof(buf), fcfg);
638                 if (!line)
639                         break;
640
641                 /* Ignore useless lines */
642                 if (line[0] == '\n' || line[0] == '#')
643                         continue;
644
645                 /* Strip final newline */
646                 if (line[strlen(line) - 1] == '\n')
647                         line[strlen(line) - 1] = 0;
648
649                 /* Parse the current line */
650                 ret = image_create_config_parse_oneline(line,
651                                                         &image_cfg[cfgi]);
652                 if (ret)
653                         return ret;
654
655                 cfgi++;
656
657                 if (cfgi >= IMAGE_CFG_ELEMENT_MAX) {
658                         fprintf(stderr,
659                                 "Too many configuration elements in .cfg file\n");
660                         return -1;
661                 }
662         }
663
664         cfgn = cfgi;
665         return 0;
666 }
667
668 static int image_get_version(void)
669 {
670         struct image_cfg_element *e;
671
672         e = image_find_option(IMAGE_CFG_VERSION);
673         if (!e)
674                 return -1;
675
676         return e->version;
677 }
678
679 static int image_version_file(const char *input)
680 {
681         FILE *fcfg;
682         int version;
683         int ret;
684
685         fcfg = fopen(input, "r");
686         if (!fcfg) {
687                 fprintf(stderr, "Could not open input file %s\n", input);
688                 return -1;
689         }
690
691         image_cfg = malloc(IMAGE_CFG_ELEMENT_MAX *
692                            sizeof(struct image_cfg_element));
693         if (!image_cfg) {
694                 fprintf(stderr, "Cannot allocate memory\n");
695                 fclose(fcfg);
696                 return -1;
697         }
698
699         memset(image_cfg, 0,
700                IMAGE_CFG_ELEMENT_MAX * sizeof(struct image_cfg_element));
701         rewind(fcfg);
702
703         ret = image_create_config_parse(fcfg);
704         fclose(fcfg);
705         if (ret) {
706                 free(image_cfg);
707                 return -1;
708         }
709
710         version = image_get_version();
711         /* Fallback to version 0 is no version is provided in the cfg file */
712         if (version == -1)
713                 version = 0;
714
715         free(image_cfg);
716
717         return version;
718 }
719
720 static void kwbimage_set_header(void *ptr, struct stat *sbuf, int ifd,
721                                 struct image_tool_params *params)
722 {
723         FILE *fcfg;
724         void *image = NULL;
725         int version;
726         size_t headersz = 0;
727         uint32_t checksum;
728         int ret;
729         int size;
730
731         fcfg = fopen(params->imagename, "r");
732         if (!fcfg) {
733                 fprintf(stderr, "Could not open input file %s\n",
734                         params->imagename);
735                 exit(EXIT_FAILURE);
736         }
737
738         image_cfg = malloc(IMAGE_CFG_ELEMENT_MAX *
739                            sizeof(struct image_cfg_element));
740         if (!image_cfg) {
741                 fprintf(stderr, "Cannot allocate memory\n");
742                 fclose(fcfg);
743                 exit(EXIT_FAILURE);
744         }
745
746         memset(image_cfg, 0,
747                IMAGE_CFG_ELEMENT_MAX * sizeof(struct image_cfg_element));
748         rewind(fcfg);
749
750         ret = image_create_config_parse(fcfg);
751         fclose(fcfg);
752         if (ret) {
753                 free(image_cfg);
754                 exit(EXIT_FAILURE);
755         }
756
757         /* The MVEBU BootROM does not allow non word aligned payloads */
758         sbuf->st_size = ALIGN_SUP(sbuf->st_size, 4);
759
760         version = image_get_version();
761         switch (version) {
762                 /*
763                  * Fallback to version 0 if no version is provided in the
764                  * cfg file
765                  */
766         case -1:
767         case 0:
768                 image = image_create_v0(&headersz, params, sbuf->st_size);
769                 break;
770
771         case 1:
772                 image = image_create_v1(&headersz, params, sbuf->st_size);
773                 break;
774
775         default:
776                 fprintf(stderr, "Unsupported version %d\n", version);
777                 free(image_cfg);
778                 exit(EXIT_FAILURE);
779         }
780
781         if (!image) {
782                 fprintf(stderr, "Could not create image\n");
783                 free(image_cfg);
784                 exit(EXIT_FAILURE);
785         }
786
787         free(image_cfg);
788
789         /* Build and add image checksum header */
790         checksum =
791                 cpu_to_le32(image_checksum32((uint32_t *)ptr, sbuf->st_size));
792         size = write(ifd, &checksum, sizeof(uint32_t));
793         if (size != sizeof(uint32_t)) {
794                 fprintf(stderr, "Error:%s - Checksum write %d bytes %s\n",
795                         params->cmdname, size, params->imagefile);
796                 exit(EXIT_FAILURE);
797         }
798
799         sbuf->st_size += sizeof(uint32_t);
800
801         /* Finally copy the header into the image area */
802         memcpy(ptr, image, headersz);
803
804         free(image);
805 }
806
807 static void kwbimage_print_header(const void *ptr)
808 {
809         struct main_hdr_v0 *mhdr = (struct main_hdr_v0 *)ptr;
810
811         printf("Image Type:   MVEBU Boot from %s Image\n",
812                image_boot_mode_name(mhdr->blockid));
813         printf("Image version:%d\n", image_version((void *)ptr));
814         printf("Data Size:    ");
815         genimg_print_size(mhdr->blocksize - sizeof(uint32_t));
816         printf("Load Address: %08x\n", mhdr->destaddr);
817         printf("Entry Point:  %08x\n", mhdr->execaddr);
818 }
819
820 static int kwbimage_check_image_types(uint8_t type)
821 {
822         if (type == IH_TYPE_KWBIMAGE)
823                 return EXIT_SUCCESS;
824
825         return EXIT_FAILURE;
826 }
827
828 static int kwbimage_verify_header(unsigned char *ptr, int image_size,
829                                   struct image_tool_params *params)
830 {
831         struct main_hdr_v0 *main_hdr;
832         uint8_t checksum;
833
834         main_hdr = (struct main_hdr_v0 *)ptr;
835         checksum = image_checksum8(ptr,
836                                    sizeof(struct main_hdr_v0)
837                                    - sizeof(uint8_t));
838         if (checksum != main_hdr->checksum)
839                 return -FDT_ERR_BADSTRUCTURE;
840
841         /* Only version 0 extended header has checksum */
842         if (image_version((void *)ptr) == 0) {
843                 struct ext_hdr_v0 *ext_hdr;
844
845                 ext_hdr = (struct ext_hdr_v0 *)
846                                 (ptr + sizeof(struct main_hdr_v0));
847                 checksum = image_checksum8(ext_hdr,
848                                            sizeof(struct ext_hdr_v0)
849                                            - sizeof(uint8_t));
850                 if (checksum != ext_hdr->checksum)
851                         return -FDT_ERR_BADSTRUCTURE;
852         }
853
854         return 0;
855 }
856
857 static int kwbimage_generate(struct image_tool_params *params,
858                              struct image_type_params *tparams)
859 {
860         int alloc_len;
861         void *hdr;
862         int version = 0;
863
864         version = image_version_file(params->imagename);
865         if (version == 0) {
866                 alloc_len = sizeof(struct main_hdr_v0) +
867                         sizeof(struct ext_hdr_v0);
868         } else {
869                 alloc_len = image_headersz_v1(NULL);
870         }
871
872         hdr = malloc(alloc_len);
873         if (!hdr) {
874                 fprintf(stderr, "%s: malloc return failure: %s\n",
875                         params->cmdname, strerror(errno));
876                 exit(EXIT_FAILURE);
877         }
878
879         memset(hdr, 0, alloc_len);
880         tparams->header_size = alloc_len;
881         tparams->hdr = hdr;
882
883         /*
884          * The resulting image needs to be 4-byte aligned. At least
885          * the Marvell hdrparser tool complains if its unaligned.
886          * By returning 1 here in this function, called via
887          * tparams->vrec_header() in mkimage.c, mkimage will
888          * automatically pad the the resulting image to a 4-byte
889          * size if necessary.
890          */
891         return 1;
892 }
893
894 /*
895  * Report Error if xflag is set in addition to default
896  */
897 static int kwbimage_check_params(struct image_tool_params *params)
898 {
899         if (!strlen(params->imagename)) {
900                 char *msg = "Configuration file for kwbimage creation omitted";
901
902                 fprintf(stderr, "Error:%s - %s\n", params->cmdname, msg);
903                 return CFG_INVALID;
904         }
905
906         return (params->dflag && (params->fflag || params->lflag)) ||
907                 (params->fflag && (params->dflag || params->lflag)) ||
908                 (params->lflag && (params->dflag || params->fflag)) ||
909                 (params->xflag) || !(strlen(params->imagename));
910 }
911
912 /*
913  * kwbimage type parameters definition
914  */
915 U_BOOT_IMAGE_TYPE(
916         kwbimage,
917         "Marvell MVEBU Boot Image support",
918         0,
919         NULL,
920         kwbimage_check_params,
921         kwbimage_verify_header,
922         kwbimage_print_header,
923         kwbimage_set_header,
924         NULL,
925         kwbimage_check_image_types,
926         NULL,
927         kwbimage_generate
928 );