]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - tools/imximage.c
Merge 'u-boot-microblaze/zynq' into (u-boot-arm/master'
[karo-tx-uboot.git] / 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 "mkimage.h"
13 #include <image.h>
14 #include "imximage.h"
15
16 /*
17  * Supported commands for configuration file
18  */
19 static table_entry_t imximage_cmds[] = {
20         {CMD_BOOT_FROM,         "BOOT_FROM",            "boot command",   },
21         {CMD_BOOT_OFFSET,       "BOOT_OFFSET",          "Boot offset",    },
22         {CMD_DATA,              "DATA",                 "Reg Write Data", },
23         {CMD_IMAGE_VERSION,     "IMAGE_VERSION",        "image version",  },
24         {-1,                    "",                     "",               },
25 };
26
27 /*
28  * Supported Boot options for configuration file
29  * this is needed to set the correct flash offset
30  */
31 static table_entry_t imximage_bootops[] = {
32         {FLASH_OFFSET_ONENAND,  "onenand",      "OneNAND Flash",},
33         {FLASH_OFFSET_NAND,     "nand",         "NAND Flash",   },
34         {FLASH_OFFSET_NOR,      "nor",          "NOR Flash",    },
35         {FLASH_OFFSET_SATA,     "sata",         "SATA Disk",    },
36         {FLASH_OFFSET_SD,       "sd",           "SD Card",      },
37         {FLASH_OFFSET_SPI,      "spi",          "SPI Flash",    },
38         {-1,                    "",             "Invalid",      },
39 };
40
41 /*
42  * IMXIMAGE version definition for i.MX chips
43  */
44 static table_entry_t imximage_versions[] = {
45         {IMXIMAGE_V1,   "",     " (i.MX25/35/51 compatible)", },
46         {IMXIMAGE_V2,   "",     " (i.MX53/6 compatible)",     },
47         {-1,            "",     " (Invalid)",                 },
48 };
49
50 static struct imx_header imximage_header;
51 static uint32_t imximage_version;
52
53 static set_dcd_val_t set_dcd_val;
54 static set_dcd_rst_t set_dcd_rst;
55 static set_imx_hdr_t set_imx_hdr;
56 static uint32_t max_dcd_entries;
57 static uint32_t *header_size_ptr;
58
59 static uint32_t get_cfg_value(char *token, char *name,  int linenr)
60 {
61         char *endptr;
62         uint32_t value;
63
64         errno = 0;
65         value = strtoul(token, &endptr, 16);
66         if (errno || (token == endptr)) {
67                 fprintf(stderr, "Error: %s[%d] - Invalid hex data(%s)\n",
68                         name,  linenr, token);
69                 exit(EXIT_FAILURE);
70         }
71         return value;
72 }
73
74 static uint32_t detect_imximage_version(struct imx_header *imx_hdr)
75 {
76         imx_header_v1_t *hdr_v1 = &imx_hdr->header.hdr_v1;
77         imx_header_v2_t *hdr_v2 = &imx_hdr->header.hdr_v2;
78         flash_header_v1_t *fhdr_v1 = &hdr_v1->fhdr;
79         flash_header_v2_t *fhdr_v2 = &hdr_v2->fhdr;
80
81         /* Try to detect V1 */
82         if ((fhdr_v1->app_code_barker == APP_CODE_BARKER) &&
83                 (hdr_v1->dcd_table.preamble.barker == DCD_BARKER))
84                 return IMXIMAGE_V1;
85
86         /* Try to detect V2 */
87         if ((fhdr_v2->header.tag == IVT_HEADER_TAG) &&
88                 (hdr_v2->dcd_table.header.tag == DCD_HEADER_TAG))
89                 return IMXIMAGE_V2;
90
91         return IMXIMAGE_VER_INVALID;
92 }
93
94 static void err_imximage_version(int version)
95 {
96         fprintf(stderr,
97                 "Error: Unsupported imximage version:%d\n", version);
98
99         exit(EXIT_FAILURE);
100 }
101
102 static void set_dcd_val_v1(struct imx_header *imxhdr, char *name, int lineno,
103                                         int fld, uint32_t value, uint32_t off)
104 {
105         dcd_v1_t *dcd_v1 = &imxhdr->header.hdr_v1.dcd_table;
106
107         switch (fld) {
108         case CFG_REG_SIZE:
109                 /* Byte, halfword, word */
110                 if ((value != 1) && (value != 2) && (value != 4)) {
111                         fprintf(stderr, "Error: %s[%d] - "
112                                 "Invalid register size " "(%d)\n",
113                                 name, lineno, value);
114                         exit(EXIT_FAILURE);
115                 }
116                 dcd_v1->addr_data[off].type = value;
117                 break;
118         case CFG_REG_ADDRESS:
119                 dcd_v1->addr_data[off].addr = value;
120                 break;
121         case CFG_REG_VALUE:
122                 dcd_v1->addr_data[off].value = value;
123                 break;
124         default:
125                 break;
126
127         }
128 }
129
130 static void set_dcd_val_v2(struct imx_header *imxhdr, char *name, int lineno,
131                                         int fld, uint32_t value, uint32_t off)
132 {
133         dcd_v2_t *dcd_v2 = &imxhdr->header.hdr_v2.dcd_table;
134
135         switch (fld) {
136         case CFG_REG_ADDRESS:
137                 dcd_v2->addr_data[off].addr = cpu_to_be32(value);
138                 break;
139         case CFG_REG_VALUE:
140                 dcd_v2->addr_data[off].value = cpu_to_be32(value);
141                 break;
142         default:
143                 break;
144
145         }
146 }
147
148 /*
149  * Complete setting up the rest field of DCD of V1
150  * such as barker code and DCD data length.
151  */
152 static void set_dcd_rst_v1(struct imx_header *imxhdr, uint32_t dcd_len,
153                                                 char *name, int lineno)
154 {
155         dcd_v1_t *dcd_v1 = &imxhdr->header.hdr_v1.dcd_table;
156
157         dcd_v1->preamble.barker = DCD_BARKER;
158         dcd_v1->preamble.length = dcd_len * sizeof(dcd_type_addr_data_t);
159 }
160
161 /*
162  * Complete setting up the reset field of DCD of V2
163  * such as DCD tag, version, length, etc.
164  */
165 static void set_dcd_rst_v2(struct imx_header *imxhdr, uint32_t dcd_len,
166                                                 char *name, int lineno)
167 {
168         dcd_v2_t *dcd_v2 = &imxhdr->header.hdr_v2.dcd_table;
169
170         dcd_v2->header.tag = DCD_HEADER_TAG;
171         dcd_v2->header.length = cpu_to_be16(
172                         dcd_len * sizeof(dcd_addr_data_t) + 8);
173         dcd_v2->header.version = DCD_VERSION;
174         dcd_v2->write_dcd_command.tag = DCD_COMMAND_TAG;
175         dcd_v2->write_dcd_command.length = cpu_to_be16(
176                         dcd_len * sizeof(dcd_addr_data_t) + 4);
177         dcd_v2->write_dcd_command.param = DCD_COMMAND_PARAM;
178 }
179
180 static void set_imx_hdr_v1(struct imx_header *imxhdr, uint32_t dcd_len,
181                 uint32_t entry_point, uint32_t flash_offset)
182 {
183         imx_header_v1_t *hdr_v1 = &imxhdr->header.hdr_v1;
184         flash_header_v1_t *fhdr_v1 = &hdr_v1->fhdr;
185         dcd_v1_t *dcd_v1 = &hdr_v1->dcd_table;
186         uint32_t hdr_base;
187         uint32_t header_length = (((char *)&dcd_v1->addr_data[dcd_len].addr)
188                         - ((char *)imxhdr));
189
190         /* Set magic number */
191         fhdr_v1->app_code_barker = APP_CODE_BARKER;
192
193         hdr_base = entry_point - sizeof(struct imx_header);
194         fhdr_v1->app_dest_ptr = hdr_base - flash_offset;
195         fhdr_v1->app_code_jump_vector = entry_point;
196
197         fhdr_v1->dcd_ptr_ptr = hdr_base + offsetof(flash_header_v1_t, dcd_ptr);
198         fhdr_v1->dcd_ptr = hdr_base + offsetof(imx_header_v1_t, dcd_table);
199
200         /* Security feature are not supported */
201         fhdr_v1->app_code_csf = 0;
202         fhdr_v1->super_root_key = 0;
203         header_size_ptr = (uint32_t *)(((char *)imxhdr) + header_length - 4);
204 }
205
206 static void set_imx_hdr_v2(struct imx_header *imxhdr, uint32_t dcd_len,
207                 uint32_t entry_point, uint32_t flash_offset)
208 {
209         imx_header_v2_t *hdr_v2 = &imxhdr->header.hdr_v2;
210         flash_header_v2_t *fhdr_v2 = &hdr_v2->fhdr;
211         uint32_t hdr_base;
212
213         /* Set magic number */
214         fhdr_v2->header.tag = IVT_HEADER_TAG; /* 0xD1 */
215         fhdr_v2->header.length = cpu_to_be16(sizeof(flash_header_v2_t));
216         fhdr_v2->header.version = IVT_VERSION; /* 0x40 */
217
218         fhdr_v2->entry = entry_point;
219         fhdr_v2->reserved1 = fhdr_v2->reserved2 = 0;
220         fhdr_v2->self = hdr_base = entry_point - sizeof(struct imx_header);
221
222         fhdr_v2->dcd_ptr = hdr_base + offsetof(imx_header_v2_t, dcd_table);
223         fhdr_v2->boot_data_ptr = hdr_base
224                         + offsetof(imx_header_v2_t, boot_data);
225         hdr_v2->boot_data.start = hdr_base - flash_offset;
226
227         /* Security feature are not supported */
228         fhdr_v2->csf = 0;
229         header_size_ptr = &hdr_v2->boot_data.size;
230 }
231
232 static void set_hdr_func(struct imx_header *imxhdr)
233 {
234         switch (imximage_version) {
235         case IMXIMAGE_V1:
236                 set_dcd_val = set_dcd_val_v1;
237                 set_dcd_rst = set_dcd_rst_v1;
238                 set_imx_hdr = set_imx_hdr_v1;
239                 max_dcd_entries = MAX_HW_CFG_SIZE_V1;
240                 break;
241         case IMXIMAGE_V2:
242                 set_dcd_val = set_dcd_val_v2;
243                 set_dcd_rst = set_dcd_rst_v2;
244                 set_imx_hdr = set_imx_hdr_v2;
245                 max_dcd_entries = MAX_HW_CFG_SIZE_V2;
246                 break;
247         default:
248                 err_imximage_version(imximage_version);
249                 break;
250         }
251 }
252
253 static void print_hdr_v1(struct imx_header *imx_hdr)
254 {
255         imx_header_v1_t *hdr_v1 = &imx_hdr->header.hdr_v1;
256         flash_header_v1_t *fhdr_v1 = &hdr_v1->fhdr;
257         dcd_v1_t *dcd_v1 = &hdr_v1->dcd_table;
258         uint32_t size, length, ver;
259
260         size = dcd_v1->preamble.length;
261         if (size > (MAX_HW_CFG_SIZE_V1 * sizeof(dcd_type_addr_data_t))) {
262                 fprintf(stderr,
263                         "Error: Image corrupt DCD size %d exceed maximum %d\n",
264                         (uint32_t)(size / sizeof(dcd_type_addr_data_t)),
265                         MAX_HW_CFG_SIZE_V1);
266                 exit(EXIT_FAILURE);
267         }
268
269         length = dcd_v1->preamble.length / sizeof(dcd_type_addr_data_t);
270         ver = detect_imximage_version(imx_hdr);
271
272         printf("Image Type:   Freescale IMX Boot Image\n");
273         printf("Image Ver:    %x", ver);
274         printf("%s\n", get_table_entry_name(imximage_versions, NULL, ver));
275         printf("Data Size:    ");
276         genimg_print_size(dcd_v1->addr_data[length].type);
277         printf("Load Address: %08x\n", (uint32_t)fhdr_v1->app_dest_ptr);
278         printf("Entry Point:  %08x\n", (uint32_t)fhdr_v1->app_code_jump_vector);
279 }
280
281 static void print_hdr_v2(struct imx_header *imx_hdr)
282 {
283         imx_header_v2_t *hdr_v2 = &imx_hdr->header.hdr_v2;
284         flash_header_v2_t *fhdr_v2 = &hdr_v2->fhdr;
285         dcd_v2_t *dcd_v2 = &hdr_v2->dcd_table;
286         uint32_t size, version;
287
288         size = be16_to_cpu(dcd_v2->header.length) - 8;
289         if (size > (MAX_HW_CFG_SIZE_V2 * sizeof(dcd_addr_data_t))) {
290                 fprintf(stderr,
291                         "Error: Image corrupt DCD size %d exceed maximum %d\n",
292                         (uint32_t)(size / sizeof(dcd_addr_data_t)),
293                         MAX_HW_CFG_SIZE_V2);
294                 exit(EXIT_FAILURE);
295         }
296
297         version = detect_imximage_version(imx_hdr);
298
299         printf("Image Type:   Freescale IMX Boot Image\n");
300         printf("Image Ver:    %x", version);
301         printf("%s\n", get_table_entry_name(imximage_versions, NULL, version));
302         printf("Data Size:    ");
303         genimg_print_size(hdr_v2->boot_data.size);
304         printf("Load Address: %08x\n", (uint32_t)fhdr_v2->boot_data_ptr);
305         printf("Entry Point:  %08x\n", (uint32_t)fhdr_v2->entry);
306 }
307
308 static void parse_cfg_cmd(struct imx_header *imxhdr, int32_t cmd, char *token,
309                                 char *name, int lineno, int fld, int dcd_len)
310 {
311         int value;
312         static int cmd_ver_first = ~0;
313
314         switch (cmd) {
315         case CMD_IMAGE_VERSION:
316                 imximage_version = get_cfg_value(token, name, lineno);
317                 if (cmd_ver_first == 0) {
318                         fprintf(stderr, "Error: %s[%d] - IMAGE_VERSION "
319                                 "command need be the first before other "
320                                 "valid command in the file\n", name, lineno);
321                         exit(EXIT_FAILURE);
322                 }
323                 cmd_ver_first = 1;
324                 set_hdr_func(imxhdr);
325                 break;
326         case CMD_BOOT_FROM:
327                 imxhdr->flash_offset = get_table_entry_id(imximage_bootops,
328                                         "imximage boot option", token);
329                 if (imxhdr->flash_offset == -1) {
330                         fprintf(stderr, "Error: %s[%d] -Invalid boot device"
331                                 "(%s)\n", name, lineno, token);
332                         exit(EXIT_FAILURE);
333                 }
334                 if (unlikely(cmd_ver_first != 1))
335                         cmd_ver_first = 0;
336                 break;
337         case CMD_BOOT_OFFSET:
338                 imxhdr->flash_offset = get_cfg_value(token, name, lineno);
339                 if (unlikely(cmd_ver_first != 1))
340                         cmd_ver_first = 0;
341                 break;
342         case CMD_DATA:
343                 value = get_cfg_value(token, name, lineno);
344                 (*set_dcd_val)(imxhdr, name, lineno, fld, value, dcd_len);
345                 if (unlikely(cmd_ver_first != 1))
346                         cmd_ver_first = 0;
347                 break;
348         }
349 }
350
351 static void parse_cfg_fld(struct imx_header *imxhdr, int32_t *cmd,
352                 char *token, char *name, int lineno, int fld, int *dcd_len)
353 {
354         int value;
355
356         switch (fld) {
357         case CFG_COMMAND:
358                 *cmd = get_table_entry_id(imximage_cmds,
359                         "imximage commands", token);
360                 if (*cmd < 0) {
361                         fprintf(stderr, "Error: %s[%d] - Invalid command"
362                         "(%s)\n", name, lineno, token);
363                         exit(EXIT_FAILURE);
364                 }
365                 break;
366         case CFG_REG_SIZE:
367                 parse_cfg_cmd(imxhdr, *cmd, token, name, lineno, fld, *dcd_len);
368                 break;
369         case CFG_REG_ADDRESS:
370         case CFG_REG_VALUE:
371                 if (*cmd != CMD_DATA)
372                         return;
373
374                 value = get_cfg_value(token, name, lineno);
375                 (*set_dcd_val)(imxhdr, name, lineno, fld, value, *dcd_len);
376
377                 if (fld == CFG_REG_VALUE) {
378                         (*dcd_len)++;
379                         if (*dcd_len > max_dcd_entries) {
380                                 fprintf(stderr, "Error: %s[%d] -"
381                                         "DCD table exceeds maximum size(%d)\n",
382                                         name, lineno, max_dcd_entries);
383                                 exit(EXIT_FAILURE);
384                         }
385                 }
386                 break;
387         default:
388                 break;
389         }
390 }
391 static uint32_t parse_cfg_file(struct imx_header *imxhdr, char *name)
392 {
393         FILE *fd = NULL;
394         char *line = NULL;
395         char *token, *saveptr1, *saveptr2;
396         int lineno = 0;
397         int fld;
398         size_t len;
399         int dcd_len = 0;
400         int32_t cmd;
401
402         fd = fopen(name, "r");
403         if (fd == 0) {
404                 fprintf(stderr, "Error: %s - Can't open DCD file\n", name);
405                 exit(EXIT_FAILURE);
406         }
407
408         /* Very simple parsing, line starting with # are comments
409          * and are dropped
410          */
411         while ((getline(&line, &len, fd)) > 0) {
412                 lineno++;
413
414                 token = strtok_r(line, "\r\n", &saveptr1);
415                 if (token == NULL)
416                         continue;
417
418                 /* Check inside the single line */
419                 for (fld = CFG_COMMAND, cmd = CMD_INVALID,
420                                 line = token; ; line = NULL, fld++) {
421                         token = strtok_r(line, " \t", &saveptr2);
422                         if (token == NULL)
423                                 break;
424
425                         /* Drop all text starting with '#' as comments */
426                         if (token[0] == '#')
427                                 break;
428
429                         parse_cfg_fld(imxhdr, &cmd, token, name,
430                                         lineno, fld, &dcd_len);
431                 }
432
433         }
434
435         (*set_dcd_rst)(imxhdr, dcd_len, name, lineno);
436         fclose(fd);
437
438         /* Exit if there is no BOOT_FROM field specifying the flash_offset */
439         if (imxhdr->flash_offset == FLASH_OFFSET_UNDEFINED) {
440                 fprintf(stderr, "Error: No BOOT_FROM tag in %s\n", name);
441                 exit(EXIT_FAILURE);
442         }
443         return dcd_len;
444 }
445
446
447 static int imximage_check_image_types(uint8_t type)
448 {
449         if (type == IH_TYPE_IMXIMAGE)
450                 return EXIT_SUCCESS;
451         else
452                 return EXIT_FAILURE;
453 }
454
455 static int imximage_verify_header(unsigned char *ptr, int image_size,
456                         struct mkimage_params *params)
457 {
458         struct imx_header *imx_hdr = (struct imx_header *) ptr;
459
460         if (detect_imximage_version(imx_hdr) == IMXIMAGE_VER_INVALID)
461                 return -FDT_ERR_BADSTRUCTURE;
462
463         return 0;
464 }
465
466 static void imximage_print_header(const void *ptr)
467 {
468         struct imx_header *imx_hdr = (struct imx_header *) ptr;
469         uint32_t version = detect_imximage_version(imx_hdr);
470
471         switch (version) {
472         case IMXIMAGE_V1:
473                 print_hdr_v1(imx_hdr);
474                 break;
475         case IMXIMAGE_V2:
476                 print_hdr_v2(imx_hdr);
477                 break;
478         default:
479                 err_imximage_version(version);
480                 break;
481         }
482 }
483
484 static void imximage_set_header(void *ptr, struct stat *sbuf, int ifd,
485                                 struct mkimage_params *params)
486 {
487         struct imx_header *imxhdr = (struct imx_header *)ptr;
488         uint32_t dcd_len;
489
490         /*
491          * In order to not change the old imx cfg file
492          * by adding VERSION command into it, here need
493          * set up function ptr group to V1 by default.
494          */
495         imximage_version = IMXIMAGE_V1;
496         /* Be able to detect if the cfg file has no BOOT_FROM tag */
497         imxhdr->flash_offset = FLASH_OFFSET_UNDEFINED;
498         set_hdr_func(imxhdr);
499
500         /* Parse dcd configuration file */
501         dcd_len = parse_cfg_file(imxhdr, params->imagename);
502
503         /* Set the imx header */
504         (*set_imx_hdr)(imxhdr, dcd_len, params->ep, imxhdr->flash_offset);
505
506         /*
507          * ROM bug alert
508          *
509          * MX53 only loads 512 byte multiples in case of SD boot.
510          * MX53 only loads NAND page multiples in case of NAND boot and
511          * supports up to 4096 byte large pages, thus align to 4096.
512          *
513          * The remaining fraction of a block bytes would not be loaded!
514          */
515         *header_size_ptr = ROUND(sbuf->st_size + imxhdr->flash_offset, 4096);
516 }
517
518 int imximage_check_params(struct mkimage_params *params)
519 {
520         if (!params)
521                 return CFG_INVALID;
522         if (!strlen(params->imagename)) {
523                 fprintf(stderr, "Error: %s - Configuration file not specified, "
524                         "it is needed for imximage generation\n",
525                         params->cmdname);
526                 return CFG_INVALID;
527         }
528         /*
529          * Check parameters:
530          * XIP is not allowed and verify that incompatible
531          * parameters are not sent at the same time
532          * For example, if list is required a data image must not be provided
533          */
534         return  (params->dflag && (params->fflag || params->lflag)) ||
535                 (params->fflag && (params->dflag || params->lflag)) ||
536                 (params->lflag && (params->dflag || params->fflag)) ||
537                 (params->xflag) || !(strlen(params->imagename));
538 }
539
540 /*
541  * imximage parameters
542  */
543 static struct image_type_params imximage_params = {
544         .name           = "Freescale i.MX Boot Image support",
545         .header_size    = sizeof(struct imx_header),
546         .hdr            = (void *)&imximage_header,
547         .check_image_type = imximage_check_image_types,
548         .verify_header  = imximage_verify_header,
549         .print_header   = imximage_print_header,
550         .set_header     = imximage_set_header,
551         .check_params   = imximage_check_params,
552 };
553
554 void init_imx_image_type(void)
555 {
556         mkimage_register(&imximage_params);
557 }