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