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