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