]> git.sur5r.net Git - u-boot/blob - tools/imximage.c
riscv: checkpatch: Fix Macro argument reuse
[u-boot] / tools / imximage.c
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 );