Merge branch 'master' of https://source.denx.de/u-boot/custodians/u-boot-riscv
[platform/kernel/u-boot.git] / tools / imximage.c
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
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
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
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
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
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
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  */
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  */
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
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
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
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
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
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
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
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
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 }
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
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
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
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
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
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
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 );