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