xref: /openbmc/u-boot/tools/imximage.c (revision cb0cb1b0)
1 /*
2  * (C) Copyright 2009
3  * Stefano Babic, DENX Software Engineering, sbabic@denx.de.
4  *
5  * (C) Copyright 2008
6  * Marvell Semiconductor <www.marvell.com>
7  * Written-by: Prafulla Wadaskar <prafulla@marvell.com>
8  *
9  * SPDX-License-Identifier:	GPL-2.0+
10  */
11 
12 #include "imagetool.h"
13 #include <image.h>
14 #include "imximage.h"
15 
16 #define UNDEFINED 0xFFFFFFFF
17 
18 /*
19  * Supported commands for configuration file
20  */
21 static table_entry_t imximage_cmds[] = {
22 	{CMD_BOOT_FROM,         "BOOT_FROM",            "boot command",	  },
23 	{CMD_BOOT_OFFSET,       "BOOT_OFFSET",          "Boot offset",	  },
24 	{CMD_WRITE_DATA,        "DATA",                 "Reg Write Data", },
25 	{CMD_WRITE_CLR_BIT,     "CLR_BIT",              "Reg clear bit",  },
26 	{CMD_WRITE_SET_BIT,     "SET_BIT",              "Reg set bit",  },
27 	{CMD_CHECK_BITS_SET,    "CHECK_BITS_SET",   "Reg Check bits set", },
28 	{CMD_CHECK_BITS_CLR,    "CHECK_BITS_CLR",   "Reg Check bits clr", },
29 	{CMD_CSF,               "CSF",           "Command Sequence File", },
30 	{CMD_IMAGE_VERSION,     "IMAGE_VERSION",        "image version",  },
31 	{CMD_PLUGIN,            "PLUGIN",               "file plugin_addr",  },
32 	{-1,                    "",                     "",	          },
33 };
34 
35 /*
36  * Supported Boot options for configuration file
37  * this is needed to set the correct flash offset
38  */
39 static table_entry_t imximage_boot_offset[] = {
40 	{FLASH_OFFSET_ONENAND,	"onenand",	"OneNAND Flash",},
41 	{FLASH_OFFSET_NAND,	"nand",		"NAND Flash",	},
42 	{FLASH_OFFSET_NOR,	"nor",		"NOR Flash",	},
43 	{FLASH_OFFSET_SATA,	"sata",		"SATA Disk",	},
44 	{FLASH_OFFSET_SD,	"sd",		"SD Card",	},
45 	{FLASH_OFFSET_SPI,	"spi",		"SPI Flash",	},
46 	{FLASH_OFFSET_QSPI,	"qspi",		"QSPI NOR Flash",},
47 	{-1,			"",		"Invalid",	},
48 };
49 
50 /*
51  * Supported Boot options for configuration file
52  * this is needed to determine the initial load size
53  */
54 static table_entry_t imximage_boot_loadsize[] = {
55 	{FLASH_LOADSIZE_ONENAND,	"onenand",	"OneNAND Flash",},
56 	{FLASH_LOADSIZE_NAND,		"nand",		"NAND Flash",	},
57 	{FLASH_LOADSIZE_NOR,		"nor",		"NOR Flash",	},
58 	{FLASH_LOADSIZE_SATA,		"sata",		"SATA Disk",	},
59 	{FLASH_LOADSIZE_SD,		"sd",		"SD Card",	},
60 	{FLASH_LOADSIZE_SPI,		"spi",		"SPI Flash",	},
61 	{FLASH_LOADSIZE_QSPI,		"qspi",		"QSPI NOR Flash",},
62 	{-1,				"",		"Invalid",	},
63 };
64 
65 /*
66  * IMXIMAGE version definition for i.MX chips
67  */
68 static table_entry_t imximage_versions[] = {
69 	{IMXIMAGE_V1,	"",	" (i.MX25/35/51 compatible)", },
70 	{IMXIMAGE_V2,	"",	" (i.MX53/6/7 compatible)",   },
71 	{-1,            "",     " (Invalid)",                 },
72 };
73 
74 static struct imx_header imximage_header;
75 static uint32_t imximage_version;
76 /*
77  * Image Vector Table Offset
78  * Initialized to a wrong not 4-bytes aligned address to
79  * check if it is was set by the cfg file.
80  */
81 static uint32_t imximage_ivt_offset = UNDEFINED;
82 static uint32_t imximage_csf_size = UNDEFINED;
83 /* Initial Load Region Size */
84 static uint32_t imximage_init_loadsize;
85 static uint32_t imximage_iram_free_start;
86 static uint32_t imximage_plugin_size;
87 static uint32_t plugin_image;
88 
89 static set_dcd_val_t set_dcd_val;
90 static set_dcd_param_t set_dcd_param;
91 static set_dcd_rst_t set_dcd_rst;
92 static set_imx_hdr_t set_imx_hdr;
93 static uint32_t max_dcd_entries;
94 static uint32_t *header_size_ptr;
95 static uint32_t *csf_ptr;
96 
97 static uint32_t get_cfg_value(char *token, char *name,  int linenr)
98 {
99 	char *endptr;
100 	uint32_t value;
101 
102 	errno = 0;
103 	value = strtoul(token, &endptr, 16);
104 	if (errno || (token == endptr)) {
105 		fprintf(stderr, "Error: %s[%d] - Invalid hex data(%s)\n",
106 			name,  linenr, token);
107 		exit(EXIT_FAILURE);
108 	}
109 	return value;
110 }
111 
112 static uint32_t detect_imximage_version(struct imx_header *imx_hdr)
113 {
114 	imx_header_v1_t *hdr_v1 = &imx_hdr->header.hdr_v1;
115 	imx_header_v2_t *hdr_v2 = &imx_hdr->header.hdr_v2;
116 	flash_header_v1_t *fhdr_v1 = &hdr_v1->fhdr;
117 	flash_header_v2_t *fhdr_v2 = &hdr_v2->fhdr;
118 
119 	/* Try to detect V1 */
120 	if ((fhdr_v1->app_code_barker == APP_CODE_BARKER) &&
121 		(hdr_v1->dcd_table.preamble.barker == DCD_BARKER))
122 		return IMXIMAGE_V1;
123 
124 	/* Try to detect V2 */
125 	if ((fhdr_v2->header.tag == IVT_HEADER_TAG) &&
126 		(hdr_v2->data.dcd_table.header.tag == DCD_HEADER_TAG))
127 		return IMXIMAGE_V2;
128 
129 	if ((fhdr_v2->header.tag == IVT_HEADER_TAG) &&
130 	    hdr_v2->boot_data.plugin)
131 		return IMXIMAGE_V2;
132 
133 	return IMXIMAGE_VER_INVALID;
134 }
135 
136 static void err_imximage_version(int version)
137 {
138 	fprintf(stderr,
139 		"Error: Unsupported imximage version:%d\n", version);
140 
141 	exit(EXIT_FAILURE);
142 }
143 
144 static void set_dcd_val_v1(struct imx_header *imxhdr, char *name, int lineno,
145 					int fld, uint32_t value, uint32_t off)
146 {
147 	dcd_v1_t *dcd_v1 = &imxhdr->header.hdr_v1.dcd_table;
148 
149 	switch (fld) {
150 	case CFG_REG_SIZE:
151 		/* Byte, halfword, word */
152 		if ((value != 1) && (value != 2) && (value != 4)) {
153 			fprintf(stderr, "Error: %s[%d] - "
154 				"Invalid register size " "(%d)\n",
155 				name, lineno, value);
156 			exit(EXIT_FAILURE);
157 		}
158 		dcd_v1->addr_data[off].type = value;
159 		break;
160 	case CFG_REG_ADDRESS:
161 		dcd_v1->addr_data[off].addr = value;
162 		break;
163 	case CFG_REG_VALUE:
164 		dcd_v1->addr_data[off].value = value;
165 		break;
166 	default:
167 		break;
168 
169 	}
170 }
171 
172 static struct dcd_v2_cmd *gd_last_cmd;
173 
174 static void set_dcd_param_v2(struct imx_header *imxhdr, uint32_t dcd_len,
175 		int32_t cmd)
176 {
177 	dcd_v2_t *dcd_v2 = &imxhdr->header.hdr_v2.data.dcd_table;
178 	struct dcd_v2_cmd *d = gd_last_cmd;
179 	struct dcd_v2_cmd *d2;
180 	int len;
181 
182 	if (!d)
183 		d = &dcd_v2->dcd_cmd;
184 	d2 = d;
185 	len = be16_to_cpu(d->write_dcd_command.length);
186 	if (len > 4)
187 		d2 = (struct dcd_v2_cmd *)(((char *)d) + len);
188 
189 	switch (cmd) {
190 	case CMD_WRITE_DATA:
191 		if ((d->write_dcd_command.tag == DCD_WRITE_DATA_COMMAND_TAG) &&
192 		    (d->write_dcd_command.param == DCD_WRITE_DATA_PARAM))
193 			break;
194 		d = d2;
195 		d->write_dcd_command.tag = DCD_WRITE_DATA_COMMAND_TAG;
196 		d->write_dcd_command.length = cpu_to_be16(4);
197 		d->write_dcd_command.param = DCD_WRITE_DATA_PARAM;
198 		break;
199 	case CMD_WRITE_CLR_BIT:
200 		if ((d->write_dcd_command.tag == DCD_WRITE_DATA_COMMAND_TAG) &&
201 		    (d->write_dcd_command.param == DCD_WRITE_CLR_BIT_PARAM))
202 			break;
203 		d = d2;
204 		d->write_dcd_command.tag = DCD_WRITE_DATA_COMMAND_TAG;
205 		d->write_dcd_command.length = cpu_to_be16(4);
206 		d->write_dcd_command.param = DCD_WRITE_CLR_BIT_PARAM;
207 		break;
208 	case CMD_WRITE_SET_BIT:
209 		if ((d->write_dcd_command.tag == DCD_WRITE_DATA_COMMAND_TAG) &&
210 		    (d->write_dcd_command.param == DCD_WRITE_SET_BIT_PARAM))
211 			break;
212 		d = d2;
213 		d->write_dcd_command.tag = DCD_WRITE_DATA_COMMAND_TAG;
214 		d->write_dcd_command.length = cpu_to_be16(4);
215 		d->write_dcd_command.param = DCD_WRITE_SET_BIT_PARAM;
216 		break;
217 	/*
218 	 * Check data command only supports one entry,
219 	 */
220 	case CMD_CHECK_BITS_SET:
221 		d = d2;
222 		d->write_dcd_command.tag = DCD_CHECK_DATA_COMMAND_TAG;
223 		d->write_dcd_command.length = cpu_to_be16(4);
224 		d->write_dcd_command.param = DCD_CHECK_BITS_SET_PARAM;
225 		break;
226 	case CMD_CHECK_BITS_CLR:
227 		d = d2;
228 		d->write_dcd_command.tag = DCD_CHECK_DATA_COMMAND_TAG;
229 		d->write_dcd_command.length = cpu_to_be16(4);
230 		d->write_dcd_command.param = DCD_CHECK_BITS_CLR_PARAM;
231 		break;
232 	default:
233 		break;
234 	}
235 	gd_last_cmd = d;
236 }
237 
238 static void set_dcd_val_v2(struct imx_header *imxhdr, char *name, int lineno,
239 					int fld, uint32_t value, uint32_t off)
240 {
241 	struct dcd_v2_cmd *d = gd_last_cmd;
242 	int len;
243 
244 	len = be16_to_cpu(d->write_dcd_command.length);
245 	off = (len - 4) >> 3;
246 
247 	switch (fld) {
248 	case CFG_REG_ADDRESS:
249 		d->addr_data[off].addr = cpu_to_be32(value);
250 		break;
251 	case CFG_REG_VALUE:
252 		d->addr_data[off].value = cpu_to_be32(value);
253 		off++;
254 		d->write_dcd_command.length = cpu_to_be16((off << 3) + 4);
255 		break;
256 	default:
257 		break;
258 
259 	}
260 }
261 
262 /*
263  * Complete setting up the rest field of DCD of V1
264  * such as barker code and DCD data length.
265  */
266 static void set_dcd_rst_v1(struct imx_header *imxhdr, uint32_t dcd_len,
267 						char *name, int lineno)
268 {
269 	dcd_v1_t *dcd_v1 = &imxhdr->header.hdr_v1.dcd_table;
270 
271 	dcd_v1->preamble.barker = DCD_BARKER;
272 	dcd_v1->preamble.length = dcd_len * sizeof(dcd_type_addr_data_t);
273 }
274 
275 /*
276  * Complete setting up the reset field of DCD of V2
277  * such as DCD tag, version, length, etc.
278  */
279 static void set_dcd_rst_v2(struct imx_header *imxhdr, uint32_t dcd_len,
280 						char *name, int lineno)
281 {
282 	if (!imxhdr->header.hdr_v2.boot_data.plugin) {
283 		dcd_v2_t *dcd_v2 = &imxhdr->header.hdr_v2.data.dcd_table;
284 		struct dcd_v2_cmd *d = gd_last_cmd;
285 		int len;
286 
287 		if (!d)
288 			d = &dcd_v2->dcd_cmd;
289 		len = be16_to_cpu(d->write_dcd_command.length);
290 		if (len > 4)
291 			d = (struct dcd_v2_cmd *)(((char *)d) + len);
292 
293 		len = (char *)d - (char *)&dcd_v2->header;
294 		dcd_v2->header.tag = DCD_HEADER_TAG;
295 		dcd_v2->header.length = cpu_to_be16(len);
296 		dcd_v2->header.version = DCD_VERSION;
297 	}
298 }
299 
300 static void set_imx_hdr_v1(struct imx_header *imxhdr, uint32_t dcd_len,
301 		uint32_t entry_point, uint32_t flash_offset)
302 {
303 	imx_header_v1_t *hdr_v1 = &imxhdr->header.hdr_v1;
304 	flash_header_v1_t *fhdr_v1 = &hdr_v1->fhdr;
305 	dcd_v1_t *dcd_v1 = &hdr_v1->dcd_table;
306 	uint32_t hdr_base;
307 	uint32_t header_length = (((char *)&dcd_v1->addr_data[dcd_len].addr)
308 			- ((char *)imxhdr));
309 
310 	/* Set magic number */
311 	fhdr_v1->app_code_barker = APP_CODE_BARKER;
312 
313 	hdr_base = entry_point - imximage_init_loadsize + flash_offset;
314 	fhdr_v1->app_dest_ptr = hdr_base - flash_offset;
315 	fhdr_v1->app_code_jump_vector = entry_point;
316 
317 	fhdr_v1->dcd_ptr_ptr = hdr_base + offsetof(flash_header_v1_t, dcd_ptr);
318 	fhdr_v1->dcd_ptr = hdr_base + offsetof(imx_header_v1_t, dcd_table);
319 
320 	/* Security feature are not supported */
321 	fhdr_v1->app_code_csf = 0;
322 	fhdr_v1->super_root_key = 0;
323 	header_size_ptr = (uint32_t *)(((char *)imxhdr) + header_length - 4);
324 }
325 
326 static void set_imx_hdr_v2(struct imx_header *imxhdr, uint32_t dcd_len,
327 		uint32_t entry_point, uint32_t flash_offset)
328 {
329 	imx_header_v2_t *hdr_v2 = &imxhdr->header.hdr_v2;
330 	flash_header_v2_t *fhdr_v2 = &hdr_v2->fhdr;
331 	uint32_t hdr_base;
332 
333 	/* Set magic number */
334 	fhdr_v2->header.tag = IVT_HEADER_TAG; /* 0xD1 */
335 	fhdr_v2->header.length = cpu_to_be16(sizeof(flash_header_v2_t));
336 	fhdr_v2->header.version = IVT_VERSION; /* 0x40 */
337 
338 	if (!hdr_v2->boot_data.plugin) {
339 		fhdr_v2->entry = entry_point;
340 		fhdr_v2->reserved1 = 0;
341 		fhdr_v2->reserved1 = 0;
342 		hdr_base = entry_point - imximage_init_loadsize +
343 			flash_offset;
344 		fhdr_v2->self = hdr_base;
345 		if (dcd_len > 0)
346 			fhdr_v2->dcd_ptr = hdr_base +
347 				offsetof(imx_header_v2_t, data);
348 		else
349 			fhdr_v2->dcd_ptr = 0;
350 		fhdr_v2->boot_data_ptr = hdr_base
351 				+ offsetof(imx_header_v2_t, boot_data);
352 		hdr_v2->boot_data.start = entry_point - imximage_init_loadsize;
353 
354 		fhdr_v2->csf = 0;
355 
356 		header_size_ptr = &hdr_v2->boot_data.size;
357 		csf_ptr = &fhdr_v2->csf;
358 	} else {
359 		imx_header_v2_t *next_hdr_v2;
360 		flash_header_v2_t *next_fhdr_v2;
361 
362 		if (imximage_csf_size != 0) {
363 			fprintf(stderr, "Error: Header v2: SECURE_BOOT is only supported in DCD mode!");
364 			exit(EXIT_FAILURE);
365 		}
366 
367 		fhdr_v2->entry = imximage_iram_free_start +
368 			flash_offset + sizeof(flash_header_v2_t) +
369 			sizeof(boot_data_t);
370 
371 		fhdr_v2->reserved1 = 0;
372 		fhdr_v2->reserved2 = 0;
373 		fhdr_v2->self = imximage_iram_free_start + flash_offset;
374 
375 		fhdr_v2->dcd_ptr = 0;
376 
377 		fhdr_v2->boot_data_ptr = fhdr_v2->self +
378 				offsetof(imx_header_v2_t, boot_data);
379 
380 		hdr_v2->boot_data.start = imximage_iram_free_start;
381 		/*
382 		 * The actural size of plugin image is "imximage_plugin_size +
383 		 * sizeof(flash_header_v2_t) + sizeof(boot_data_t)", plus the
384 		 * flash_offset space.The ROM code only need to copy this size
385 		 * to run the plugin code. However, later when copy the whole
386 		 * U-Boot image to DDR, the ROM code use memcpy to copy the
387 		 * first part of the image, and use the storage read function
388 		 * to get the remaining part. This requires the dividing point
389 		 * must be multiple of storage sector size. Here we set the
390 		 * first section to be MAX_PLUGIN_CODE_SIZE(64KB) for this
391 		 * purpose.
392 		 */
393 		hdr_v2->boot_data.size = MAX_PLUGIN_CODE_SIZE;
394 
395 		/* Security feature are not supported */
396 		fhdr_v2->csf = 0;
397 
398 		next_hdr_v2 = (imx_header_v2_t *)((char *)hdr_v2 +
399 			       imximage_plugin_size);
400 
401 		next_fhdr_v2 = &next_hdr_v2->fhdr;
402 
403 		next_fhdr_v2->header.tag = IVT_HEADER_TAG; /* 0xD1 */
404 		next_fhdr_v2->header.length =
405 			cpu_to_be16(sizeof(flash_header_v2_t));
406 		next_fhdr_v2->header.version = IVT_VERSION; /* 0x40 */
407 
408 		next_fhdr_v2->entry = entry_point;
409 		hdr_base = entry_point - sizeof(struct imx_header);
410 		next_fhdr_v2->reserved1 = 0;
411 		next_fhdr_v2->reserved2 = 0;
412 		next_fhdr_v2->self = hdr_base + imximage_plugin_size;
413 
414 		next_fhdr_v2->dcd_ptr = 0;
415 		next_fhdr_v2->boot_data_ptr = next_fhdr_v2->self +
416 				offsetof(imx_header_v2_t, boot_data);
417 
418 		next_hdr_v2->boot_data.start = hdr_base - flash_offset;
419 
420 		header_size_ptr = &next_hdr_v2->boot_data.size;
421 
422 		next_hdr_v2->boot_data.plugin = 0;
423 
424 		next_fhdr_v2->csf = 0;
425 	}
426 }
427 
428 static void set_hdr_func(void)
429 {
430 	switch (imximage_version) {
431 	case IMXIMAGE_V1:
432 		set_dcd_val = set_dcd_val_v1;
433 		set_dcd_param = NULL;
434 		set_dcd_rst = set_dcd_rst_v1;
435 		set_imx_hdr = set_imx_hdr_v1;
436 		max_dcd_entries = MAX_HW_CFG_SIZE_V1;
437 		break;
438 	case IMXIMAGE_V2:
439 		gd_last_cmd = NULL;
440 		set_dcd_val = set_dcd_val_v2;
441 		set_dcd_param = set_dcd_param_v2;
442 		set_dcd_rst = set_dcd_rst_v2;
443 		set_imx_hdr = set_imx_hdr_v2;
444 		max_dcd_entries = MAX_HW_CFG_SIZE_V2;
445 		break;
446 	default:
447 		err_imximage_version(imximage_version);
448 		break;
449 	}
450 }
451 
452 static void print_hdr_v1(struct imx_header *imx_hdr)
453 {
454 	imx_header_v1_t *hdr_v1 = &imx_hdr->header.hdr_v1;
455 	flash_header_v1_t *fhdr_v1 = &hdr_v1->fhdr;
456 	dcd_v1_t *dcd_v1 = &hdr_v1->dcd_table;
457 	uint32_t size, length, ver;
458 
459 	size = dcd_v1->preamble.length;
460 	if (size > (MAX_HW_CFG_SIZE_V1 * sizeof(dcd_type_addr_data_t))) {
461 		fprintf(stderr,
462 			"Error: Image corrupt DCD size %d exceed maximum %d\n",
463 			(uint32_t)(size / sizeof(dcd_type_addr_data_t)),
464 			MAX_HW_CFG_SIZE_V1);
465 		exit(EXIT_FAILURE);
466 	}
467 
468 	length = dcd_v1->preamble.length / sizeof(dcd_type_addr_data_t);
469 	ver = detect_imximage_version(imx_hdr);
470 
471 	printf("Image Type:   Freescale IMX Boot Image\n");
472 	printf("Image Ver:    %x", ver);
473 	printf("%s\n", get_table_entry_name(imximage_versions, NULL, ver));
474 	printf("Data Size:    ");
475 	genimg_print_size(dcd_v1->addr_data[length].type);
476 	printf("Load Address: %08x\n", (uint32_t)fhdr_v1->app_dest_ptr);
477 	printf("Entry Point:  %08x\n", (uint32_t)fhdr_v1->app_code_jump_vector);
478 }
479 
480 static void print_hdr_v2(struct imx_header *imx_hdr)
481 {
482 	imx_header_v2_t *hdr_v2 = &imx_hdr->header.hdr_v2;
483 	flash_header_v2_t *fhdr_v2 = &hdr_v2->fhdr;
484 	dcd_v2_t *dcd_v2 = &hdr_v2->data.dcd_table;
485 	uint32_t size, version, plugin;
486 
487 	plugin = hdr_v2->boot_data.plugin;
488 	if (!plugin) {
489 		size = be16_to_cpu(dcd_v2->header.length);
490 		if (size > (MAX_HW_CFG_SIZE_V2 * sizeof(dcd_addr_data_t))) {
491 			fprintf(stderr,
492 				"Error: Image corrupt DCD size %d exceed maximum %d\n",
493 				(uint32_t)(size / sizeof(dcd_addr_data_t)),
494 				MAX_HW_CFG_SIZE_V2);
495 			exit(EXIT_FAILURE);
496 		}
497 	}
498 
499 	version = detect_imximage_version(imx_hdr);
500 
501 	printf("Image Type:   Freescale IMX Boot Image\n");
502 	printf("Image Ver:    %x", version);
503 	printf("%s\n", get_table_entry_name(imximage_versions, NULL, version));
504 	printf("Mode:         %s\n", plugin ? "PLUGIN" : "DCD");
505 	if (!plugin) {
506 		printf("Data Size:    ");
507 		genimg_print_size(hdr_v2->boot_data.size);
508 		printf("Load Address: %08x\n", (uint32_t)fhdr_v2->boot_data_ptr);
509 		printf("Entry Point:  %08x\n", (uint32_t)fhdr_v2->entry);
510 		if (fhdr_v2->csf && (imximage_ivt_offset != UNDEFINED) &&
511 		    (imximage_csf_size != UNDEFINED)) {
512 			uint16_t dcdlen;
513 			int offs;
514 
515 			dcdlen = hdr_v2->data.dcd_table.header.length;
516 			offs = (char *)&hdr_v2->data.dcd_table
517 				- (char *)hdr_v2;
518 
519 			printf("HAB Blocks:   %08x %08x %08x\n",
520 			       (uint32_t)fhdr_v2->self, 0,
521 			       hdr_v2->boot_data.size - imximage_ivt_offset -
522 			       imximage_csf_size);
523 			printf("DCD Blocks:   00910000 %08x %08x\n",
524 			       offs, be16_to_cpu(dcdlen));
525 		}
526 	} else {
527 		imx_header_v2_t *next_hdr_v2;
528 		flash_header_v2_t *next_fhdr_v2;
529 
530 		/*First Header*/
531 		printf("Plugin Data Size:     ");
532 		genimg_print_size(hdr_v2->boot_data.size);
533 		printf("Plugin Code Size:     ");
534 		genimg_print_size(imximage_plugin_size);
535 		printf("Plugin Load Address:  %08x\n", hdr_v2->boot_data.start);
536 		printf("Plugin Entry Point:   %08x\n", (uint32_t)fhdr_v2->entry);
537 
538 		/*Second Header*/
539 		next_hdr_v2 = (imx_header_v2_t *)((char *)hdr_v2 +
540 				imximage_plugin_size);
541 		next_fhdr_v2 = &next_hdr_v2->fhdr;
542 		printf("U-Boot Data Size:     ");
543 		genimg_print_size(next_hdr_v2->boot_data.size);
544 		printf("U-Boot Load Address:  %08x\n",
545 		       next_hdr_v2->boot_data.start);
546 		printf("U-Boot Entry Point:   %08x\n",
547 		       (uint32_t)next_fhdr_v2->entry);
548 	}
549 }
550 
551 static void copy_plugin_code(struct imx_header *imxhdr, char *plugin_file)
552 {
553 	int ifd;
554 	struct stat sbuf;
555 	char *plugin_buf = imxhdr->header.hdr_v2.data.plugin_code;
556 	char *ptr;
557 
558 	ifd = open(plugin_file, O_RDONLY|O_BINARY);
559 	if (ifd < 0) {
560 		fprintf(stderr, "Can't open %s: %s\n",
561 			plugin_file,
562 			strerror(errno));
563 		exit(EXIT_FAILURE);
564 	}
565 
566 	if (fstat(ifd, &sbuf) < 0) {
567 		fprintf(stderr, "Can't stat %s: %s\n",
568 			plugin_file,
569 			strerror(errno));
570 		exit(EXIT_FAILURE);
571 	}
572 
573 	ptr = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, ifd, 0);
574 	if (ptr == MAP_FAILED) {
575 		fprintf(stderr, "Can't read %s: %s\n",
576 			plugin_file,
577 			strerror(errno));
578 		exit(EXIT_FAILURE);
579 	}
580 
581 	if (sbuf.st_size > MAX_PLUGIN_CODE_SIZE) {
582 		printf("plugin binary size too large\n");
583 		exit(EXIT_FAILURE);
584 	}
585 
586 	memcpy(plugin_buf, ptr, sbuf.st_size);
587 	imximage_plugin_size = sbuf.st_size;
588 
589 	(void) munmap((void *)ptr, sbuf.st_size);
590 	(void) close(ifd);
591 
592 	imxhdr->header.hdr_v2.boot_data.plugin = 1;
593 }
594 
595 static void parse_cfg_cmd(struct imx_header *imxhdr, int32_t cmd, char *token,
596 				char *name, int lineno, int fld, int dcd_len)
597 {
598 	int value;
599 	static int cmd_ver_first = ~0;
600 
601 	switch (cmd) {
602 	case CMD_IMAGE_VERSION:
603 		imximage_version = get_cfg_value(token, name, lineno);
604 		if (cmd_ver_first == 0) {
605 			fprintf(stderr, "Error: %s[%d] - IMAGE_VERSION "
606 				"command need be the first before other "
607 				"valid command in the file\n", name, lineno);
608 			exit(EXIT_FAILURE);
609 		}
610 		cmd_ver_first = 1;
611 		set_hdr_func();
612 		break;
613 	case CMD_BOOT_FROM:
614 		imximage_ivt_offset = get_table_entry_id(imximage_boot_offset,
615 					"imximage boot option", token);
616 		if (imximage_ivt_offset == -1) {
617 			fprintf(stderr, "Error: %s[%d] -Invalid boot device"
618 				"(%s)\n", name, lineno, token);
619 			exit(EXIT_FAILURE);
620 		}
621 
622 		imximage_init_loadsize =
623 			get_table_entry_id(imximage_boot_loadsize,
624 					   "imximage boot option", token);
625 
626 		if (imximage_init_loadsize == -1) {
627 			fprintf(stderr,
628 				"Error: %s[%d] -Invalid boot device(%s)\n",
629 				name, lineno, token);
630 			exit(EXIT_FAILURE);
631 		}
632 
633 		/*
634 		 * The SOC loads from the storage starting at address 0
635 		 * then ensures that the load size contains the offset
636 		 */
637 		if (imximage_init_loadsize < imximage_ivt_offset)
638 			imximage_init_loadsize = imximage_ivt_offset;
639 		if (unlikely(cmd_ver_first != 1))
640 			cmd_ver_first = 0;
641 		break;
642 	case CMD_BOOT_OFFSET:
643 		imximage_ivt_offset = get_cfg_value(token, name, lineno);
644 		if (unlikely(cmd_ver_first != 1))
645 			cmd_ver_first = 0;
646 		break;
647 	case CMD_WRITE_DATA:
648 	case CMD_WRITE_CLR_BIT:
649 	case CMD_WRITE_SET_BIT:
650 	case CMD_CHECK_BITS_SET:
651 	case CMD_CHECK_BITS_CLR:
652 		value = get_cfg_value(token, name, lineno);
653 		if (set_dcd_param)
654 			(*set_dcd_param)(imxhdr, dcd_len, cmd);
655 		(*set_dcd_val)(imxhdr, name, lineno, fld, value, dcd_len);
656 		if (unlikely(cmd_ver_first != 1))
657 			cmd_ver_first = 0;
658 		break;
659 	case CMD_CSF:
660 		if (imximage_version != 2) {
661 			fprintf(stderr,
662 				"Error: %s[%d] - CSF only supported for VERSION 2(%s)\n",
663 				name, lineno, token);
664 			exit(EXIT_FAILURE);
665 		}
666 		imximage_csf_size = get_cfg_value(token, name, lineno);
667 		if (unlikely(cmd_ver_first != 1))
668 			cmd_ver_first = 0;
669 		break;
670 	case CMD_PLUGIN:
671 		plugin_image = 1;
672 		copy_plugin_code(imxhdr, token);
673 		break;
674 	}
675 }
676 
677 static void parse_cfg_fld(struct imx_header *imxhdr, int32_t *cmd,
678 		char *token, char *name, int lineno, int fld, int *dcd_len)
679 {
680 	int value;
681 
682 	switch (fld) {
683 	case CFG_COMMAND:
684 		*cmd = get_table_entry_id(imximage_cmds,
685 			"imximage commands", token);
686 		if (*cmd < 0) {
687 			fprintf(stderr, "Error: %s[%d] - Invalid command"
688 			"(%s)\n", name, lineno, token);
689 			exit(EXIT_FAILURE);
690 		}
691 		break;
692 	case CFG_REG_SIZE:
693 		parse_cfg_cmd(imxhdr, *cmd, token, name, lineno, fld, *dcd_len);
694 		break;
695 	case CFG_REG_ADDRESS:
696 	case CFG_REG_VALUE:
697 		switch(*cmd) {
698 		case CMD_WRITE_DATA:
699 		case CMD_WRITE_CLR_BIT:
700 		case CMD_WRITE_SET_BIT:
701 		case CMD_CHECK_BITS_SET:
702 		case CMD_CHECK_BITS_CLR:
703 
704 			value = get_cfg_value(token, name, lineno);
705 			if (set_dcd_param)
706 				(*set_dcd_param)(imxhdr, *dcd_len, *cmd);
707 			(*set_dcd_val)(imxhdr, name, lineno, fld, value,
708 					*dcd_len);
709 
710 			if (fld == CFG_REG_VALUE) {
711 				(*dcd_len)++;
712 				if (*dcd_len > max_dcd_entries) {
713 					fprintf(stderr, "Error: %s[%d] -"
714 						"DCD table exceeds maximum size(%d)\n",
715 						name, lineno, max_dcd_entries);
716 					exit(EXIT_FAILURE);
717 				}
718 			}
719 			break;
720 		case CMD_PLUGIN:
721 			value = get_cfg_value(token, name, lineno);
722 			imximage_iram_free_start = value;
723 			break;
724 		default:
725 			break;
726 		}
727 		break;
728 	default:
729 		break;
730 	}
731 }
732 static uint32_t parse_cfg_file(struct imx_header *imxhdr, char *name)
733 {
734 	FILE *fd = NULL;
735 	char *line = NULL;
736 	char *token, *saveptr1, *saveptr2;
737 	int lineno = 0;
738 	int fld;
739 	size_t len;
740 	int dcd_len = 0;
741 	int32_t cmd;
742 
743 	fd = fopen(name, "r");
744 	if (fd == 0) {
745 		fprintf(stderr, "Error: %s - Can't open DCD file\n", name);
746 		exit(EXIT_FAILURE);
747 	}
748 
749 	/*
750 	 * Very simple parsing, line starting with # are comments
751 	 * and are dropped
752 	 */
753 	while ((getline(&line, &len, fd)) > 0) {
754 		lineno++;
755 
756 		token = strtok_r(line, "\r\n", &saveptr1);
757 		if (token == NULL)
758 			continue;
759 
760 		/* Check inside the single line */
761 		for (fld = CFG_COMMAND, cmd = CMD_INVALID,
762 				line = token; ; line = NULL, fld++) {
763 			token = strtok_r(line, " \t", &saveptr2);
764 			if (token == NULL)
765 				break;
766 
767 			/* Drop all text starting with '#' as comments */
768 			if (token[0] == '#')
769 				break;
770 
771 			parse_cfg_fld(imxhdr, &cmd, token, name,
772 					lineno, fld, &dcd_len);
773 		}
774 
775 	}
776 
777 	(*set_dcd_rst)(imxhdr, dcd_len, name, lineno);
778 	fclose(fd);
779 
780 	return dcd_len;
781 }
782 
783 
784 static int imximage_check_image_types(uint8_t type)
785 {
786 	if (type == IH_TYPE_IMXIMAGE)
787 		return EXIT_SUCCESS;
788 	else
789 		return EXIT_FAILURE;
790 }
791 
792 static int imximage_verify_header(unsigned char *ptr, int image_size,
793 			struct image_tool_params *params)
794 {
795 	struct imx_header *imx_hdr = (struct imx_header *) ptr;
796 
797 	if (detect_imximage_version(imx_hdr) == IMXIMAGE_VER_INVALID)
798 		return -FDT_ERR_BADSTRUCTURE;
799 
800 	return 0;
801 }
802 
803 static void imximage_print_header(const void *ptr)
804 {
805 	struct imx_header *imx_hdr = (struct imx_header *) ptr;
806 	uint32_t version = detect_imximage_version(imx_hdr);
807 
808 	switch (version) {
809 	case IMXIMAGE_V1:
810 		print_hdr_v1(imx_hdr);
811 		break;
812 	case IMXIMAGE_V2:
813 		print_hdr_v2(imx_hdr);
814 		break;
815 	default:
816 		err_imximage_version(version);
817 		break;
818 	}
819 }
820 
821 static void imximage_set_header(void *ptr, struct stat *sbuf, int ifd,
822 				struct image_tool_params *params)
823 {
824 	struct imx_header *imxhdr = (struct imx_header *)ptr;
825 	uint32_t dcd_len;
826 	uint32_t header_size;
827 
828 	/*
829 	 * In order to not change the old imx cfg file
830 	 * by adding VERSION command into it, here need
831 	 * set up function ptr group to V1 by default.
832 	 */
833 	imximage_version = IMXIMAGE_V1;
834 	/* Be able to detect if the cfg file has no BOOT_FROM tag */
835 	imximage_ivt_offset = FLASH_OFFSET_UNDEFINED;
836 	imximage_csf_size = 0;
837 	set_hdr_func();
838 
839 	/* Parse dcd configuration file */
840 	dcd_len = parse_cfg_file(imxhdr, params->imagename);
841 
842 	if (imximage_version == IMXIMAGE_V1)
843 		header_size = sizeof(flash_header_v1_t);
844 	else {
845 		header_size = sizeof(flash_header_v2_t) + sizeof(boot_data_t);
846 		if (!plugin_image)
847 			header_size += sizeof(dcd_v2_t);
848 		else
849 			header_size += MAX_PLUGIN_CODE_SIZE;
850 	}
851 
852 	if (imximage_init_loadsize < imximage_ivt_offset + header_size)
853 			imximage_init_loadsize = imximage_ivt_offset + header_size;
854 
855 	/* Set the imx header */
856 	(*set_imx_hdr)(imxhdr, dcd_len, params->ep, imximage_ivt_offset);
857 
858 	/*
859 	 * ROM bug alert
860 	 *
861 	 * MX53 only loads 512 byte multiples in case of SD boot.
862 	 * MX53 only loads NAND page multiples in case of NAND boot and
863 	 * supports up to 4096 byte large pages, thus align to 4096.
864 	 *
865 	 * The remaining fraction of a block bytes would not be loaded!
866 	 */
867 	*header_size_ptr = ROUND((sbuf->st_size + imximage_ivt_offset), 4096);
868 
869 	if (csf_ptr && imximage_csf_size) {
870 		*csf_ptr = params->ep - imximage_init_loadsize +
871 			*header_size_ptr;
872 		*header_size_ptr += imximage_csf_size;
873 	}
874 }
875 
876 int imximage_check_params(struct image_tool_params *params)
877 {
878 	if (!params)
879 		return CFG_INVALID;
880 	if (!strlen(params->imagename)) {
881 		fprintf(stderr, "Error: %s - Configuration file not specified, "
882 			"it is needed for imximage generation\n",
883 			params->cmdname);
884 		return CFG_INVALID;
885 	}
886 	/*
887 	 * Check parameters:
888 	 * XIP is not allowed and verify that incompatible
889 	 * parameters are not sent at the same time
890 	 * For example, if list is required a data image must not be provided
891 	 */
892 	return	(params->dflag && (params->fflag || params->lflag)) ||
893 		(params->fflag && (params->dflag || params->lflag)) ||
894 		(params->lflag && (params->dflag || params->fflag)) ||
895 		(params->xflag) || !(strlen(params->imagename));
896 }
897 
898 static int imximage_generate(struct image_tool_params *params,
899 	struct image_type_params *tparams)
900 {
901 	struct imx_header *imxhdr;
902 	size_t alloc_len;
903 	struct stat sbuf;
904 	char *datafile = params->datafile;
905 	uint32_t pad_len, header_size;
906 
907 	memset(&imximage_header, 0, sizeof(imximage_header));
908 
909 	/*
910 	 * In order to not change the old imx cfg file
911 	 * by adding VERSION command into it, here need
912 	 * set up function ptr group to V1 by default.
913 	 */
914 	imximage_version = IMXIMAGE_V1;
915 	/* Be able to detect if the cfg file has no BOOT_FROM tag */
916 	imximage_ivt_offset = FLASH_OFFSET_UNDEFINED;
917 	imximage_csf_size = 0;
918 	set_hdr_func();
919 
920 	/* Parse dcd configuration file */
921 	parse_cfg_file(&imximage_header, params->imagename);
922 
923 	if (imximage_version == IMXIMAGE_V1)
924 		header_size = sizeof(imx_header_v1_t);
925 	else {
926 		header_size = sizeof(flash_header_v2_t) + sizeof(boot_data_t);
927 		if (!plugin_image)
928 			header_size += sizeof(dcd_v2_t);
929 		else
930 			header_size += MAX_PLUGIN_CODE_SIZE;
931 	}
932 
933 	if (imximage_init_loadsize < imximage_ivt_offset + header_size)
934 			imximage_init_loadsize = imximage_ivt_offset + header_size;
935 
936 	alloc_len = imximage_init_loadsize - imximage_ivt_offset;
937 
938 	if (alloc_len < header_size) {
939 		fprintf(stderr, "%s: header error\n",
940 			params->cmdname);
941 		exit(EXIT_FAILURE);
942 	}
943 
944 	imxhdr = malloc(alloc_len);
945 
946 	if (!imxhdr) {
947 		fprintf(stderr, "%s: malloc return failure: %s\n",
948 			params->cmdname, strerror(errno));
949 		exit(EXIT_FAILURE);
950 	}
951 
952 	memset(imxhdr, 0, alloc_len);
953 
954 	tparams->header_size = alloc_len;
955 	tparams->hdr         = imxhdr;
956 
957 	/* determine data image file length */
958 
959 	if (stat(datafile, &sbuf) < 0) {
960 		fprintf(stderr, "%s: Can't stat %s: %s\n",
961 			params->cmdname, datafile, strerror(errno));
962 		exit(EXIT_FAILURE);
963 	}
964 
965 	pad_len = ROUND(sbuf.st_size, 4096) - sbuf.st_size;
966 
967 	return pad_len;
968 }
969 
970 
971 /*
972  * imximage parameters
973  */
974 U_BOOT_IMAGE_TYPE(
975 	imximage,
976 	"Freescale i.MX Boot Image support",
977 	0,
978 	NULL,
979 	imximage_check_params,
980 	imximage_verify_header,
981 	imximage_print_header,
982 	imximage_set_header,
983 	NULL,
984 	imximage_check_image_types,
985 	NULL,
986 	imximage_generate
987 );
988