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