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