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