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