]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - tools/mxsimage.c
dm: gpio: hi6220: Add a hi6220 GPIO driver model driver.
[karo-tx-uboot.git] / tools / mxsimage.c
1 /*
2  * Freescale i.MX23/i.MX28 SB image generator
3  *
4  * Copyright (C) 2012-2013 Marek Vasut <marex@denx.de>
5  *
6  * SPDX-License-Identifier:     GPL-2.0+
7  */
8
9 #ifdef CONFIG_MXS
10
11 #include <errno.h>
12 #include <fcntl.h>
13 #include <stdio.h>
14 #include <string.h>
15 #include <unistd.h>
16 #include <limits.h>
17
18 #include <openssl/evp.h>
19
20 #include "imagetool.h"
21 #include "mxsimage.h"
22 #include "pbl_crc32.h"
23 #include <image.h>
24
25
26 /*
27  * DCD block
28  * |-Write to address command block
29  * |  0xf00 == 0xf33d
30  * |  0xba2 == 0xb33f
31  * |-ORR address with mask command block
32  * |  0xf00 |= 0x1337
33  * |-Write to address command block
34  * |  0xba2 == 0xd00d
35  * :
36  */
37 #define SB_HAB_DCD_WRITE        0xccUL
38 #define SB_HAB_DCD_CHECK        0xcfUL
39 #define SB_HAB_DCD_NOOP         0xc0UL
40 #define SB_HAB_DCD_MASK_BIT     (1 << 3)
41 #define SB_HAB_DCD_SET_BIT      (1 << 4)
42
43 /* Addr.n = Value.n */
44 #define SB_DCD_WRITE    \
45         (SB_HAB_DCD_WRITE << 24)
46 /* Addr.n &= ~Value.n */
47 #define SB_DCD_ANDC     \
48         ((SB_HAB_DCD_WRITE << 24) | SB_HAB_DCD_SET_BIT)
49 /* Addr.n |= Value.n */
50 #define SB_DCD_ORR      \
51         ((SB_HAB_DCD_WRITE << 24) | SB_HAB_DCD_SET_BIT | SB_HAB_DCD_MASK_BIT)
52 /* (Addr.n & Value.n) == 0 */
53 #define SB_DCD_CHK_EQZ  \
54         (SB_HAB_DCD_CHECK << 24)
55 /* (Addr.n & Value.n) == Value.n */
56 #define SB_DCD_CHK_EQ   \
57         ((SB_HAB_DCD_CHECK << 24) | SB_HAB_DCD_SET_BIT)
58 /* (Addr.n & Value.n) != Value.n */
59 #define SB_DCD_CHK_NEQ  \
60         ((SB_HAB_DCD_CHECK << 24) | SB_HAB_DCD_MASK_BIT)
61 /* (Addr.n & Value.n) != 0 */
62 #define SB_DCD_CHK_NEZ  \
63         ((SB_HAB_DCD_CHECK << 24) | SB_HAB_DCD_SET_BIT | SB_HAB_DCD_MASK_BIT)
64 /* NOP */
65 #define SB_DCD_NOOP     \
66         (SB_HAB_DCD_NOOP << 24)
67
68 struct sb_dcd_ctx {
69         struct sb_dcd_ctx               *dcd;
70
71         uint32_t                        id;
72
73         /* The DCD block. */
74         uint32_t                        *payload;
75         /* Size of the whole DCD block. */
76         uint32_t                        size;
77
78         /* Pointer to previous DCD command block. */
79         uint32_t                        *prev_dcd_head;
80 };
81
82 /*
83  * IMAGE
84  *   |-SECTION
85  *   |    |-CMD
86  *   |    |-CMD
87  *   |    `-CMD
88  *   |-SECTION
89  *   |    |-CMD
90  *   :    :
91  */
92 struct sb_cmd_list {
93         char                            *cmd;
94         size_t                          len;
95         unsigned int                    lineno;
96 };
97
98 struct sb_cmd_ctx {
99         uint32_t                        size;
100
101         struct sb_cmd_ctx               *cmd;
102
103         uint8_t                         *data;
104         uint32_t                        length;
105
106         struct sb_command               payload;
107         struct sb_command               c_payload;
108 };
109
110 struct sb_section_ctx {
111         uint32_t                        size;
112
113         /* Section flags */
114         unsigned int                    boot:1;
115
116         struct sb_section_ctx           *sect;
117
118         struct sb_cmd_ctx               *cmd_head;
119         struct sb_cmd_ctx               *cmd_tail;
120
121         struct sb_sections_header       payload;
122 };
123
124 struct sb_image_ctx {
125         unsigned int                    in_section:1;
126         unsigned int                    in_dcd:1;
127         /* Image configuration */
128         unsigned int                    display_progress:1;
129         unsigned int                    silent_dump:1;
130         char                            *input_filename;
131         char                            *output_filename;
132         char                            *cfg_filename;
133         uint8_t                         image_key[16];
134
135         /* Number of section in the image */
136         unsigned int                    sect_count;
137         /* Bootable section */
138         unsigned int                    sect_boot;
139         unsigned int                    sect_boot_found:1;
140
141         struct sb_section_ctx           *sect_head;
142         struct sb_section_ctx           *sect_tail;
143
144         struct sb_dcd_ctx               *dcd_head;
145         struct sb_dcd_ctx               *dcd_tail;
146
147         EVP_CIPHER_CTX                  cipher_ctx;
148         EVP_MD_CTX                      md_ctx;
149         uint8_t                         digest[32];
150         struct sb_key_dictionary_key    sb_dict_key;
151
152         struct sb_boot_image_header     payload;
153 };
154
155 /*
156  * Instruction semantics:
157  * NOOP
158  * TAG [LAST]
159  * LOAD       address file
160  * LOAD  IVT  address IVT_entry_point
161  * FILL address pattern length
162  * JUMP [HAB] address [r0_arg]
163  * CALL [HAB] address [r0_arg]
164  * MODE mode
165  *      For i.MX23, mode = USB/I2C/SPI1_FLASH/SPI2_FLASH/NAND_BCH
166  *                         JTAG/SPI3_EEPROM/SD_SSP0/SD_SSP1
167  *      For i.MX28, mode = USB/I2C/SPI2_FLASH/SPI3_FLASH/NAND_BCH
168  *                         JTAG/SPI2_EEPROM/SD_SSP0/SD_SSP1
169  */
170
171 /*
172  * AES libcrypto
173  */
174 static int sb_aes_init(struct sb_image_ctx *ictx, uint8_t *iv, int enc)
175 {
176         EVP_CIPHER_CTX *ctx = &ictx->cipher_ctx;
177         int ret;
178
179         /* If there is no init vector, init vector is all zeroes. */
180         if (!iv)
181                 iv = ictx->image_key;
182
183         EVP_CIPHER_CTX_init(ctx);
184         ret = EVP_CipherInit(ctx, EVP_aes_128_cbc(), ictx->image_key, iv, enc);
185         if (ret == 1)
186                 EVP_CIPHER_CTX_set_padding(ctx, 0);
187         return ret;
188 }
189
190 static int sb_aes_crypt(struct sb_image_ctx *ictx, uint8_t *in_data,
191                         uint8_t *out_data, int in_len)
192 {
193         EVP_CIPHER_CTX *ctx = &ictx->cipher_ctx;
194         int ret, outlen;
195         uint8_t *outbuf;
196
197         outbuf = malloc(in_len);
198         if (!outbuf)
199                 return -ENOMEM;
200         memset(outbuf, 0, sizeof(in_len));
201
202         ret = EVP_CipherUpdate(ctx, outbuf, &outlen, in_data, in_len);
203         if (!ret) {
204                 ret = -EINVAL;
205                 goto err;
206         }
207
208         if (out_data)
209                 memcpy(out_data, outbuf, outlen);
210
211 err:
212         free(outbuf);
213         return ret;
214 }
215
216 static int sb_aes_deinit(EVP_CIPHER_CTX *ctx)
217 {
218         return EVP_CIPHER_CTX_cleanup(ctx);
219 }
220
221 static int sb_aes_reinit(struct sb_image_ctx *ictx, int enc)
222 {
223         int ret;
224         EVP_CIPHER_CTX *ctx = &ictx->cipher_ctx;
225         struct sb_boot_image_header *sb_header = &ictx->payload;
226         uint8_t *iv = sb_header->iv;
227
228         ret = sb_aes_deinit(ctx);
229         if (!ret)
230                 return ret;
231         return sb_aes_init(ictx, iv, enc);
232 }
233
234 /*
235  * Debug
236  */
237 static void soprintf(struct sb_image_ctx *ictx, const char *fmt, ...)
238 {
239         va_list ap;
240
241         if (ictx->silent_dump)
242                 return;
243
244         va_start(ap, fmt);
245         vfprintf(stdout, fmt, ap);
246         va_end(ap);
247 }
248
249 /*
250  * Code
251  */
252 static time_t sb_get_timestamp(void)
253 {
254         struct tm time_2000 = {
255                 .tm_yday        = 1,    /* Jan. 1st */
256                 .tm_year        = 100,  /* 2000 */
257         };
258         time_t seconds_to_2000 = mktime(&time_2000);
259         time_t seconds_to_now = time(NULL);
260
261         return seconds_to_now - seconds_to_2000;
262 }
263
264 static int sb_get_time(time_t time, struct tm *tm)
265 {
266         struct tm time_2000 = {
267                 .tm_yday        = 1,    /* Jan. 1st */
268                 .tm_year        = 0,    /* 1900 */
269         };
270         const time_t seconds_to_2000 = mktime(&time_2000);
271         const time_t seconds_to_now = seconds_to_2000 + time;
272         struct tm *ret;
273         ret = gmtime_r(&seconds_to_now, tm);
274         return ret ? 0 : -EINVAL;
275 }
276
277 static void sb_encrypt_sb_header(struct sb_image_ctx *ictx)
278 {
279         EVP_MD_CTX *md_ctx = &ictx->md_ctx;
280         struct sb_boot_image_header *sb_header = &ictx->payload;
281         uint8_t *sb_header_ptr = (uint8_t *)sb_header;
282
283         /* Encrypt the header, compute the digest. */
284         sb_aes_crypt(ictx, sb_header_ptr, NULL, sizeof(*sb_header));
285         EVP_DigestUpdate(md_ctx, sb_header_ptr, sizeof(*sb_header));
286 }
287
288 static void sb_encrypt_sb_sections_header(struct sb_image_ctx *ictx)
289 {
290         EVP_MD_CTX *md_ctx = &ictx->md_ctx;
291         struct sb_section_ctx *sctx = ictx->sect_head;
292         struct sb_sections_header *shdr;
293         uint8_t *sb_sections_header_ptr;
294         const int size = sizeof(*shdr);
295
296         while (sctx) {
297                 shdr = &sctx->payload;
298                 sb_sections_header_ptr = (uint8_t *)shdr;
299
300                 sb_aes_crypt(ictx, sb_sections_header_ptr,
301                              ictx->sb_dict_key.cbc_mac, size);
302                 EVP_DigestUpdate(md_ctx, sb_sections_header_ptr, size);
303
304                 sctx = sctx->sect;
305         };
306 }
307
308 static void sb_encrypt_key_dictionary_key(struct sb_image_ctx *ictx)
309 {
310         EVP_MD_CTX *md_ctx = &ictx->md_ctx;
311
312         sb_aes_crypt(ictx, ictx->image_key, ictx->sb_dict_key.key,
313                      sizeof(ictx->sb_dict_key.key));
314         EVP_DigestUpdate(md_ctx, &ictx->sb_dict_key, sizeof(ictx->sb_dict_key));
315 }
316
317 static void sb_decrypt_key_dictionary_key(struct sb_image_ctx *ictx)
318 {
319         EVP_MD_CTX *md_ctx = &ictx->md_ctx;
320
321         EVP_DigestUpdate(md_ctx, &ictx->sb_dict_key, sizeof(ictx->sb_dict_key));
322         sb_aes_crypt(ictx, ictx->sb_dict_key.key, ictx->image_key,
323                      sizeof(ictx->sb_dict_key.key));
324 }
325
326 static void sb_encrypt_tag(struct sb_image_ctx *ictx,
327                 struct sb_cmd_ctx *cctx)
328 {
329         EVP_MD_CTX *md_ctx = &ictx->md_ctx;
330         struct sb_command *cmd = &cctx->payload;
331
332         sb_aes_crypt(ictx, (uint8_t *)cmd,
333                      (uint8_t *)&cctx->c_payload, sizeof(*cmd));
334         EVP_DigestUpdate(md_ctx, &cctx->c_payload, sizeof(*cmd));
335 }
336
337 static int sb_encrypt_image(struct sb_image_ctx *ictx)
338 {
339         /* Start image-wide crypto. */
340         EVP_MD_CTX_init(&ictx->md_ctx);
341         EVP_DigestInit(&ictx->md_ctx, EVP_sha1());
342
343         /*
344          * SB image header.
345          */
346         sb_aes_init(ictx, NULL, 1);
347         sb_encrypt_sb_header(ictx);
348
349         /*
350          * SB sections header.
351          */
352         sb_encrypt_sb_sections_header(ictx);
353
354         /*
355          * Key dictionary.
356          */
357         sb_aes_reinit(ictx, 1);
358         sb_encrypt_key_dictionary_key(ictx);
359
360         /*
361          * Section tags.
362          */
363         struct sb_cmd_ctx *cctx;
364         struct sb_command *ccmd;
365         struct sb_section_ctx *sctx = ictx->sect_head;
366
367         while (sctx) {
368                 cctx = sctx->cmd_head;
369
370                 sb_aes_reinit(ictx, 1);
371
372                 while (cctx) {
373                         ccmd = &cctx->payload;
374
375                         sb_encrypt_tag(ictx, cctx);
376
377                         if (ccmd->header.tag == ROM_TAG_CMD) {
378                                 sb_aes_reinit(ictx, 1);
379                         } else if (ccmd->header.tag == ROM_LOAD_CMD) {
380                                 sb_aes_crypt(ictx, cctx->data, cctx->data,
381                                              cctx->length);
382                                 EVP_DigestUpdate(&ictx->md_ctx, cctx->data,
383                                                  cctx->length);
384                         }
385
386                         cctx = cctx->cmd;
387                 }
388
389                 sctx = sctx->sect;
390         };
391
392         /*
393          * Dump the SHA1 of the whole image.
394          */
395         sb_aes_reinit(ictx, 1);
396
397         EVP_DigestFinal(&ictx->md_ctx, ictx->digest, NULL);
398         sb_aes_crypt(ictx, ictx->digest, ictx->digest, sizeof(ictx->digest));
399
400         /* Stop the encryption session. */
401         sb_aes_deinit(&ictx->cipher_ctx);
402
403         return 0;
404 }
405
406 static int sb_load_file(struct sb_cmd_ctx *cctx, char *filename)
407 {
408         long real_size, roundup_size;
409         uint8_t *data;
410         long ret;
411         unsigned long size;
412         FILE *fp;
413
414         if (!filename) {
415                 fprintf(stderr, "ERR: Missing filename!\n");
416                 return -EINVAL;
417         }
418
419         fp = fopen(filename, "r");
420         if (!fp)
421                 goto err_open;
422
423         ret = fseek(fp, 0, SEEK_END);
424         if (ret < 0)
425                 goto err_file;
426
427         real_size = ftell(fp);
428         if (real_size < 0)
429                 goto err_file;
430
431         ret = fseek(fp, 0, SEEK_SET);
432         if (ret < 0)
433                 goto err_file;
434
435         roundup_size = roundup(real_size, SB_BLOCK_SIZE);
436         data = calloc(1, roundup_size);
437         if (!data)
438                 goto err_file;
439
440         size = fread(data, 1, real_size, fp);
441         if (size != (unsigned long)real_size)
442                 goto err_alloc;
443
444         cctx->data = data;
445         cctx->length = roundup_size;
446
447         fclose(fp);
448         return 0;
449
450 err_alloc:
451         free(data);
452 err_file:
453         fclose(fp);
454 err_open:
455         fprintf(stderr, "ERR: Failed to load file \"%s\"\n", filename);
456         return -EINVAL;
457 }
458
459 static uint8_t sb_command_checksum(struct sb_command *inst)
460 {
461         uint8_t *inst_ptr = (uint8_t *)inst;
462         uint8_t csum = 0;
463         unsigned int i;
464
465         for (i = 0; i < sizeof(struct sb_command); i++)
466                 csum += inst_ptr[i];
467
468         return csum;
469 }
470
471 static int sb_token_to_long(char *tok, uint32_t *rid)
472 {
473         char *endptr;
474         unsigned long id;
475
476         if (tok[0] != '0' || tok[1] != 'x') {
477                 fprintf(stderr, "ERR: Invalid hexadecimal number!\n");
478                 return -EINVAL;
479         }
480
481         tok += 2;
482
483         errno = 0;
484         id = strtoul(tok, &endptr, 16);
485         if ((errno == ERANGE && id == ULONG_MAX) || (errno != 0 && id == 0)) {
486                 fprintf(stderr, "ERR: Value can't be decoded!\n");
487                 return -EINVAL;
488         }
489
490         /* Check for 32-bit overflow. */
491         if (id > 0xffffffff) {
492                 fprintf(stderr, "ERR: Value too big!\n");
493                 return -EINVAL;
494         }
495
496         if (endptr == tok) {
497                 fprintf(stderr, "ERR: Deformed value!\n");
498                 return -EINVAL;
499         }
500
501         *rid = (uint32_t)id;
502         return 0;
503 }
504
505 static int sb_grow_dcd(struct sb_dcd_ctx *dctx, unsigned int inc_size)
506 {
507         uint32_t *tmp;
508
509         if (!inc_size)
510                 return 0;
511
512         dctx->size += inc_size;
513         tmp = realloc(dctx->payload, dctx->size);
514         if (!tmp)
515                 return -ENOMEM;
516
517         dctx->payload = tmp;
518
519         /* Assemble and update the HAB DCD header. */
520         dctx->payload[0] = htonl((SB_HAB_DCD_TAG << 24) |
521                                  (dctx->size << 8) |
522                                  SB_HAB_VERSION);
523
524         return 0;
525 }
526
527 static int sb_build_dcd(struct sb_image_ctx *ictx, struct sb_cmd_list *cmd)
528 {
529         struct sb_dcd_ctx *dctx;
530
531         char *tok;
532         uint32_t id;
533         int ret;
534
535         dctx = calloc(1, sizeof(*dctx));
536         if (!dctx)
537                 return -ENOMEM;
538
539         ret = sb_grow_dcd(dctx, 4);
540         if (ret)
541                 goto err_dcd;
542
543         /* Read DCD block number. */
544         tok = strtok(cmd->cmd, " ");
545         if (!tok) {
546                 fprintf(stderr, "#%i ERR: DCD block without number!\n",
547                         cmd->lineno);
548                 ret = -EINVAL;
549                 goto err_dcd;
550         }
551
552         /* Parse the DCD block number. */
553         ret = sb_token_to_long(tok, &id);
554         if (ret) {
555                 fprintf(stderr, "#%i ERR: Malformed DCD block number!\n",
556                         cmd->lineno);
557                 goto err_dcd;
558         }
559
560         dctx->id = id;
561
562         /*
563          * The DCD block is now constructed. Append it to the list.
564          * WARNING: The DCD size is still not computed and will be
565          * updated while parsing it's commands.
566          */
567         if (!ictx->dcd_head) {
568                 ictx->dcd_head = dctx;
569                 ictx->dcd_tail = dctx;
570         } else {
571                 ictx->dcd_tail->dcd = dctx;
572                 ictx->dcd_tail = dctx;
573         }
574
575         return 0;
576
577 err_dcd:
578         free(dctx->payload);
579         free(dctx);
580         return ret;
581 }
582
583 static int sb_build_dcd_block(struct sb_image_ctx *ictx,
584                               struct sb_cmd_list *cmd,
585                               uint32_t type)
586 {
587         char *tok;
588         uint32_t address, value, length;
589         int ret;
590
591         struct sb_dcd_ctx *dctx = ictx->dcd_tail;
592         uint32_t *dcd;
593
594         if (dctx->prev_dcd_head && (type != SB_DCD_NOOP) &&
595             ((dctx->prev_dcd_head[0] & 0xff0000ff) == type)) {
596                 /* Same instruction as before, just append it. */
597                 ret = sb_grow_dcd(dctx, 8);
598                 if (ret)
599                         return ret;
600         } else if (type == SB_DCD_NOOP) {
601                 ret = sb_grow_dcd(dctx, 4);
602                 if (ret)
603                         return ret;
604
605                 /* Update DCD command block pointer. */
606                 dctx->prev_dcd_head = dctx->payload +
607                                 dctx->size / sizeof(*dctx->payload) - 1;
608
609                 /* NOOP has only 4 bytes and no payload. */
610                 goto noop;
611         } else {
612                 /*
613                  * Either a different instruction block started now
614                  * or this is the first instruction block.
615                  */
616                 ret = sb_grow_dcd(dctx, 12);
617                 if (ret)
618                         return ret;
619
620                 /* Update DCD command block pointer. */
621                 dctx->prev_dcd_head = dctx->payload +
622                                 dctx->size / sizeof(*dctx->payload) - 3;
623         }
624
625         dcd = dctx->payload + dctx->size / sizeof(*dctx->payload) - 2;
626
627         /*
628          * Prepare the command.
629          */
630         tok = strtok(cmd->cmd, " ");
631         if (!tok) {
632                 fprintf(stderr, "#%i ERR: Missing DCD address!\n",
633                         cmd->lineno);
634                 ret = -EINVAL;
635                 goto err;
636         }
637
638         /* Read DCD destination address. */
639         ret = sb_token_to_long(tok, &address);
640         if (ret) {
641                 fprintf(stderr, "#%i ERR: Incorrect DCD address!\n",
642                         cmd->lineno);
643                 goto err;
644         }
645
646         tok = strtok(NULL, " ");
647         if (!tok) {
648                 fprintf(stderr, "#%i ERR: Missing DCD value!\n",
649                         cmd->lineno);
650                 ret = -EINVAL;
651                 goto err;
652         }
653
654         /* Read DCD operation value. */
655         ret = sb_token_to_long(tok, &value);
656         if (ret) {
657                 fprintf(stderr, "#%i ERR: Incorrect DCD value!\n",
658                         cmd->lineno);
659                 goto err;
660         }
661
662         /* Fill in the new DCD entry. */
663         dcd[0] = htonl(address);
664         dcd[1] = htonl(value);
665
666 noop:
667         /* Update the DCD command block. */
668         length = dctx->size -
669                  ((dctx->prev_dcd_head - dctx->payload) *
670                  sizeof(*dctx->payload));
671         dctx->prev_dcd_head[0] = htonl(type | (length << 8));
672
673 err:
674         return ret;
675 }
676
677 static int sb_build_section(struct sb_image_ctx *ictx, struct sb_cmd_list *cmd)
678 {
679         struct sb_section_ctx *sctx;
680         struct sb_sections_header *shdr;
681         char *tok;
682         uint32_t bootable = 0;
683         uint32_t id;
684         int ret;
685
686         sctx = calloc(1, sizeof(*sctx));
687         if (!sctx)
688                 return -ENOMEM;
689
690         /* Read section number. */
691         tok = strtok(cmd->cmd, " ");
692         if (!tok) {
693                 fprintf(stderr, "#%i ERR: Section without number!\n",
694                         cmd->lineno);
695                 ret = -EINVAL;
696                 goto err_sect;
697         }
698
699         /* Parse the section number. */
700         ret = sb_token_to_long(tok, &id);
701         if (ret) {
702                 fprintf(stderr, "#%i ERR: Malformed section number!\n",
703                         cmd->lineno);
704                 goto err_sect;
705         }
706
707         /* Read section's BOOTABLE flag. */
708         tok = strtok(NULL, " ");
709         if (tok && (strlen(tok) == 8) && !strncmp(tok, "BOOTABLE", 8))
710                 bootable = SB_SECTION_FLAG_BOOTABLE;
711
712         sctx->boot = bootable;
713
714         shdr = &sctx->payload;
715         shdr->section_number = id;
716         shdr->section_flags = bootable;
717
718         /*
719          * The section is now constructed. Append it to the list.
720          * WARNING: The section size is still not computed and will
721          * be updated while parsing it's commands.
722          */
723         ictx->sect_count++;
724
725         /* Mark that this section is bootable one. */
726         if (bootable) {
727                 if (ictx->sect_boot_found) {
728                         fprintf(stderr,
729                                 "#%i WARN: Multiple bootable section!\n",
730                                 cmd->lineno);
731                 } else {
732                         ictx->sect_boot = id;
733                         ictx->sect_boot_found = 1;
734                 }
735         }
736
737         if (!ictx->sect_head) {
738                 ictx->sect_head = sctx;
739                 ictx->sect_tail = sctx;
740         } else {
741                 ictx->sect_tail->sect = sctx;
742                 ictx->sect_tail = sctx;
743         }
744
745         return 0;
746
747 err_sect:
748         free(sctx);
749         return ret;
750 }
751
752 static int sb_build_command_nop(struct sb_image_ctx *ictx)
753 {
754         struct sb_section_ctx *sctx = ictx->sect_tail;
755         struct sb_cmd_ctx *cctx;
756         struct sb_command *ccmd;
757
758         cctx = calloc(1, sizeof(*cctx));
759         if (!cctx)
760                 return -ENOMEM;
761
762         ccmd = &cctx->payload;
763
764         /*
765          * Construct the command.
766          */
767         ccmd->header.checksum   = 0x5a;
768         ccmd->header.tag        = ROM_NOP_CMD;
769
770         cctx->size = sizeof(*ccmd);
771
772         /*
773          * Append the command to the last section.
774          */
775         if (!sctx->cmd_head) {
776                 sctx->cmd_head = cctx;
777                 sctx->cmd_tail = cctx;
778         } else {
779                 sctx->cmd_tail->cmd = cctx;
780                 sctx->cmd_tail = cctx;
781         }
782
783         return 0;
784 }
785
786 static int sb_build_command_tag(struct sb_image_ctx *ictx,
787                                 struct sb_cmd_list *cmd)
788 {
789         struct sb_section_ctx *sctx = ictx->sect_tail;
790         struct sb_cmd_ctx *cctx;
791         struct sb_command *ccmd;
792         char *tok;
793
794         cctx = calloc(1, sizeof(*cctx));
795         if (!cctx)
796                 return -ENOMEM;
797
798         ccmd = &cctx->payload;
799
800         /*
801          * Prepare the command.
802          */
803         /* Check for the LAST keyword. */
804         tok = strtok(cmd->cmd, " ");
805         if (tok && !strcmp(tok, "LAST"))
806                 ccmd->header.flags = ROM_TAG_CMD_FLAG_ROM_LAST_TAG;
807
808         /*
809          * Construct the command.
810          */
811         ccmd->header.checksum   = 0x5a;
812         ccmd->header.tag        = ROM_TAG_CMD;
813
814         cctx->size = sizeof(*ccmd);
815
816         /*
817          * Append the command to the last section.
818          */
819         if (!sctx->cmd_head) {
820                 sctx->cmd_head = cctx;
821                 sctx->cmd_tail = cctx;
822         } else {
823                 sctx->cmd_tail->cmd = cctx;
824                 sctx->cmd_tail = cctx;
825         }
826
827         return 0;
828 }
829
830 static int sb_build_command_load(struct sb_image_ctx *ictx,
831                                  struct sb_cmd_list *cmd)
832 {
833         struct sb_section_ctx *sctx = ictx->sect_tail;
834         struct sb_cmd_ctx *cctx;
835         struct sb_command *ccmd;
836         char *tok;
837         int ret, is_ivt = 0, is_dcd = 0;
838         uint32_t dest, dcd = 0;
839
840         cctx = calloc(1, sizeof(*cctx));
841         if (!cctx)
842                 return -ENOMEM;
843
844         ccmd = &cctx->payload;
845
846         /*
847          * Prepare the command.
848          */
849         tok = strtok(cmd->cmd, " ");
850         if (!tok) {
851                 fprintf(stderr, "#%i ERR: Missing LOAD address or 'IVT'!\n",
852                         cmd->lineno);
853                 ret = -EINVAL;
854                 goto err;
855         }
856
857         /* Check for "IVT" flag. */
858         if (!strcmp(tok, "IVT"))
859                 is_ivt = 1;
860         if (!strcmp(tok, "DCD"))
861                 is_dcd = 1;
862         if (is_ivt || is_dcd) {
863                 tok = strtok(NULL, " ");
864                 if (!tok) {
865                         fprintf(stderr, "#%i ERR: Missing LOAD address!\n",
866                                 cmd->lineno);
867                         ret = -EINVAL;
868                         goto err;
869                 }
870         }
871
872         /* Read load destination address. */
873         ret = sb_token_to_long(tok, &dest);
874         if (ret) {
875                 fprintf(stderr, "#%i ERR: Incorrect LOAD address!\n",
876                         cmd->lineno);
877                 goto err;
878         }
879
880         /* Read filename or IVT entrypoint or DCD block ID. */
881         tok = strtok(NULL, " ");
882         if (!tok) {
883                 fprintf(stderr,
884                         "#%i ERR: Missing LOAD filename or IVT ep or DCD block ID!\n",
885                         cmd->lineno);
886                 ret = -EINVAL;
887                 goto err;
888         }
889
890         if (is_ivt) {
891                 /* Handle IVT. */
892                 struct sb_ivt_header *ivt;
893                 uint32_t ivtep;
894                 ret = sb_token_to_long(tok, &ivtep);
895
896                 if (ret) {
897                         fprintf(stderr,
898                                 "#%i ERR: Incorrect IVT entry point!\n",
899                                 cmd->lineno);
900                         goto err;
901                 }
902
903                 ivt = calloc(1, sizeof(*ivt));
904                 if (!ivt) {
905                         ret = -ENOMEM;
906                         goto err;
907                 }
908
909                 ivt->header = sb_hab_ivt_header();
910                 ivt->entry = ivtep;
911                 ivt->self = dest;
912
913                 cctx->data = (uint8_t *)ivt;
914                 cctx->length = sizeof(*ivt);
915         } else if (is_dcd) {
916                 struct sb_dcd_ctx *dctx = ictx->dcd_head;
917                 uint32_t dcdid;
918                 uint8_t *payload;
919                 uint32_t asize;
920                 ret = sb_token_to_long(tok, &dcdid);
921
922                 if (ret) {
923                         fprintf(stderr,
924                                 "#%i ERR: Incorrect DCD block ID!\n",
925                                 cmd->lineno);
926                         goto err;
927                 }
928
929                 while (dctx) {
930                         if (dctx->id == dcdid)
931                                 break;
932                         dctx = dctx->dcd;
933                 }
934
935                 if (!dctx) {
936                         fprintf(stderr, "#%i ERR: DCD block %08x not found!\n",
937                                 cmd->lineno, dcdid);
938                         goto err;
939                 }
940
941                 asize = roundup(dctx->size, SB_BLOCK_SIZE);
942                 payload = calloc(1, asize);
943                 if (!payload) {
944                         ret = -ENOMEM;
945                         goto err;
946                 }
947
948                 memcpy(payload, dctx->payload, dctx->size);
949
950                 cctx->data = payload;
951                 cctx->length = asize;
952
953                 /* Set the Load DCD flag. */
954                 dcd = ROM_LOAD_CMD_FLAG_DCD_LOAD;
955         } else {
956                 /* Regular LOAD of a file. */
957                 ret = sb_load_file(cctx, tok);
958                 if (ret) {
959                         fprintf(stderr, "#%i ERR: Cannot load '%s'!\n",
960                                 cmd->lineno, tok);
961                         goto err;
962                 }
963         }
964
965         if (cctx->length & (SB_BLOCK_SIZE - 1)) {
966                 fprintf(stderr, "#%i ERR: Unaligned payload!\n",
967                         cmd->lineno);
968         }
969
970         /*
971          * Construct the command.
972          */
973         ccmd->header.checksum   = 0x5a;
974         ccmd->header.tag        = ROM_LOAD_CMD;
975         ccmd->header.flags      = dcd;
976
977         ccmd->load.address      = dest;
978         ccmd->load.count        = cctx->length;
979         ccmd->load.crc32        = pbl_crc32(0,
980                                             (const char *)cctx->data,
981                                             cctx->length);
982
983         cctx->size = sizeof(*ccmd) + cctx->length;
984
985         /*
986          * Append the command to the last section.
987          */
988         if (!sctx->cmd_head) {
989                 sctx->cmd_head = cctx;
990                 sctx->cmd_tail = cctx;
991         } else {
992                 sctx->cmd_tail->cmd = cctx;
993                 sctx->cmd_tail = cctx;
994         }
995
996         return 0;
997
998 err:
999         free(cctx);
1000         return ret;
1001 }
1002
1003 static int sb_build_command_fill(struct sb_image_ctx *ictx,
1004                                  struct sb_cmd_list *cmd)
1005 {
1006         struct sb_section_ctx *sctx = ictx->sect_tail;
1007         struct sb_cmd_ctx *cctx;
1008         struct sb_command *ccmd;
1009         char *tok;
1010         uint32_t address, pattern, length;
1011         int ret;
1012
1013         cctx = calloc(1, sizeof(*cctx));
1014         if (!cctx)
1015                 return -ENOMEM;
1016
1017         ccmd = &cctx->payload;
1018
1019         /*
1020          * Prepare the command.
1021          */
1022         tok = strtok(cmd->cmd, " ");
1023         if (!tok) {
1024                 fprintf(stderr, "#%i ERR: Missing FILL address!\n",
1025                         cmd->lineno);
1026                 ret = -EINVAL;
1027                 goto err;
1028         }
1029
1030         /* Read fill destination address. */
1031         ret = sb_token_to_long(tok, &address);
1032         if (ret) {
1033                 fprintf(stderr, "#%i ERR: Incorrect FILL address!\n",
1034                         cmd->lineno);
1035                 goto err;
1036         }
1037
1038         tok = strtok(NULL, " ");
1039         if (!tok) {
1040                 fprintf(stderr, "#%i ERR: Missing FILL pattern!\n",
1041                         cmd->lineno);
1042                 ret = -EINVAL;
1043                 goto err;
1044         }
1045
1046         /* Read fill pattern address. */
1047         ret = sb_token_to_long(tok, &pattern);
1048         if (ret) {
1049                 fprintf(stderr, "#%i ERR: Incorrect FILL pattern!\n",
1050                         cmd->lineno);
1051                 goto err;
1052         }
1053
1054         tok = strtok(NULL, " ");
1055         if (!tok) {
1056                 fprintf(stderr, "#%i ERR: Missing FILL length!\n",
1057                         cmd->lineno);
1058                 ret = -EINVAL;
1059                 goto err;
1060         }
1061
1062         /* Read fill pattern address. */
1063         ret = sb_token_to_long(tok, &length);
1064         if (ret) {
1065                 fprintf(stderr, "#%i ERR: Incorrect FILL length!\n",
1066                         cmd->lineno);
1067                 goto err;
1068         }
1069
1070         /*
1071          * Construct the command.
1072          */
1073         ccmd->header.checksum   = 0x5a;
1074         ccmd->header.tag        = ROM_FILL_CMD;
1075
1076         ccmd->fill.address      = address;
1077         ccmd->fill.count        = length;
1078         ccmd->fill.pattern      = pattern;
1079
1080         cctx->size = sizeof(*ccmd);
1081
1082         /*
1083          * Append the command to the last section.
1084          */
1085         if (!sctx->cmd_head) {
1086                 sctx->cmd_head = cctx;
1087                 sctx->cmd_tail = cctx;
1088         } else {
1089                 sctx->cmd_tail->cmd = cctx;
1090                 sctx->cmd_tail = cctx;
1091         }
1092
1093         return 0;
1094
1095 err:
1096         free(cctx);
1097         return ret;
1098 }
1099
1100 static int sb_build_command_jump_call(struct sb_image_ctx *ictx,
1101                                       struct sb_cmd_list *cmd,
1102                                       unsigned int is_call)
1103 {
1104         struct sb_section_ctx *sctx = ictx->sect_tail;
1105         struct sb_cmd_ctx *cctx;
1106         struct sb_command *ccmd;
1107         char *tok;
1108         uint32_t dest, arg = 0x0;
1109         uint32_t hab = 0;
1110         int ret;
1111         const char *cmdname = is_call ? "CALL" : "JUMP";
1112
1113         cctx = calloc(1, sizeof(*cctx));
1114         if (!cctx)
1115                 return -ENOMEM;
1116
1117         ccmd = &cctx->payload;
1118
1119         /*
1120          * Prepare the command.
1121          */
1122         tok = strtok(cmd->cmd, " ");
1123         if (!tok) {
1124                 fprintf(stderr,
1125                         "#%i ERR: Missing %s address or 'HAB'!\n",
1126                         cmd->lineno, cmdname);
1127                 ret = -EINVAL;
1128                 goto err;
1129         }
1130
1131         /* Check for "HAB" flag. */
1132         if (!strcmp(tok, "HAB")) {
1133                 hab = is_call ? ROM_CALL_CMD_FLAG_HAB : ROM_JUMP_CMD_FLAG_HAB;
1134                 tok = strtok(NULL, " ");
1135                 if (!tok) {
1136                         fprintf(stderr, "#%i ERR: Missing %s address!\n",
1137                                 cmd->lineno, cmdname);
1138                         ret = -EINVAL;
1139                         goto err;
1140                 }
1141         }
1142         /* Read load destination address. */
1143         ret = sb_token_to_long(tok, &dest);
1144         if (ret) {
1145                 fprintf(stderr, "#%i ERR: Incorrect %s address!\n",
1146                         cmd->lineno, cmdname);
1147                 goto err;
1148         }
1149
1150         tok = strtok(NULL, " ");
1151         if (tok) {
1152                 ret = sb_token_to_long(tok, &arg);
1153                 if (ret) {
1154                         fprintf(stderr,
1155                                 "#%i ERR: Incorrect %s argument!\n",
1156                                 cmd->lineno, cmdname);
1157                         goto err;
1158                 }
1159         }
1160
1161         /*
1162          * Construct the command.
1163          */
1164         ccmd->header.checksum   = 0x5a;
1165         ccmd->header.tag        = is_call ? ROM_CALL_CMD : ROM_JUMP_CMD;
1166         ccmd->header.flags      = hab;
1167
1168         ccmd->call.address      = dest;
1169         ccmd->call.argument     = arg;
1170
1171         cctx->size = sizeof(*ccmd);
1172
1173         /*
1174          * Append the command to the last section.
1175          */
1176         if (!sctx->cmd_head) {
1177                 sctx->cmd_head = cctx;
1178                 sctx->cmd_tail = cctx;
1179         } else {
1180                 sctx->cmd_tail->cmd = cctx;
1181                 sctx->cmd_tail = cctx;
1182         }
1183
1184         return 0;
1185
1186 err:
1187         free(cctx);
1188         return ret;
1189 }
1190
1191 static int sb_build_command_jump(struct sb_image_ctx *ictx,
1192                                  struct sb_cmd_list *cmd)
1193 {
1194         return sb_build_command_jump_call(ictx, cmd, 0);
1195 }
1196
1197 static int sb_build_command_call(struct sb_image_ctx *ictx,
1198                                  struct sb_cmd_list *cmd)
1199 {
1200         return sb_build_command_jump_call(ictx, cmd, 1);
1201 }
1202
1203 static int sb_build_command_mode(struct sb_image_ctx *ictx,
1204                                  struct sb_cmd_list *cmd)
1205 {
1206         struct sb_section_ctx *sctx = ictx->sect_tail;
1207         struct sb_cmd_ctx *cctx;
1208         struct sb_command *ccmd;
1209         char *tok;
1210         int ret;
1211         unsigned int i;
1212         uint32_t mode = 0xffffffff;
1213
1214         cctx = calloc(1, sizeof(*cctx));
1215         if (!cctx)
1216                 return -ENOMEM;
1217
1218         ccmd = &cctx->payload;
1219
1220         /*
1221          * Prepare the command.
1222          */
1223         tok = strtok(cmd->cmd, " ");
1224         if (!tok) {
1225                 fprintf(stderr, "#%i ERR: Missing MODE boot mode argument!\n",
1226                         cmd->lineno);
1227                 ret = -EINVAL;
1228                 goto err;
1229         }
1230
1231         for (i = 0; i < ARRAY_SIZE(modetable); i++) {
1232                 if (!strcmp(tok, modetable[i].name)) {
1233                         mode = modetable[i].mode;
1234                         break;
1235                 }
1236
1237                 if (!modetable[i].altname)
1238                         continue;
1239
1240                 if (!strcmp(tok, modetable[i].altname)) {
1241                         mode = modetable[i].mode;
1242                         break;
1243                 }
1244         }
1245
1246         if (mode == 0xffffffff) {
1247                 fprintf(stderr, "#%i ERR: Invalid MODE boot mode argument!\n",
1248                         cmd->lineno);
1249                 ret = -EINVAL;
1250                 goto err;
1251         }
1252
1253         /*
1254          * Construct the command.
1255          */
1256         ccmd->header.checksum   = 0x5a;
1257         ccmd->header.tag        = ROM_MODE_CMD;
1258
1259         ccmd->mode.mode         = mode;
1260
1261         cctx->size = sizeof(*ccmd);
1262
1263         /*
1264          * Append the command to the last section.
1265          */
1266         if (!sctx->cmd_head) {
1267                 sctx->cmd_head = cctx;
1268                 sctx->cmd_tail = cctx;
1269         } else {
1270                 sctx->cmd_tail->cmd = cctx;
1271                 sctx->cmd_tail = cctx;
1272         }
1273
1274         return 0;
1275
1276 err:
1277         free(cctx);
1278         return ret;
1279 }
1280
1281 static int sb_prefill_image_header(struct sb_image_ctx *ictx)
1282 {
1283         struct sb_boot_image_header *hdr = &ictx->payload;
1284
1285         /* Fill signatures */
1286         memcpy(hdr->signature1, "STMP", 4);
1287         memcpy(hdr->signature2, "sgtl", 4);
1288
1289         /* SB Image version 1.1 */
1290         hdr->major_version = SB_VERSION_MAJOR;
1291         hdr->minor_version = SB_VERSION_MINOR;
1292
1293         /* Boot image major version */
1294         hdr->product_version.major = htons(0x999);
1295         hdr->product_version.minor = htons(0x999);
1296         hdr->product_version.revision = htons(0x999);
1297         /* Boot image major version */
1298         hdr->component_version.major = htons(0x999);
1299         hdr->component_version.minor = htons(0x999);
1300         hdr->component_version.revision = htons(0x999);
1301
1302         /* Drive tag must be 0x0 for i.MX23 */
1303         hdr->drive_tag = 0;
1304
1305         hdr->header_blocks =
1306                 sizeof(struct sb_boot_image_header) / SB_BLOCK_SIZE;
1307         hdr->section_header_size =
1308                 sizeof(struct sb_sections_header) / SB_BLOCK_SIZE;
1309         hdr->timestamp_us = sb_get_timestamp() * 1000000;
1310
1311         hdr->flags = ictx->display_progress ?
1312                 SB_IMAGE_FLAG_DISPLAY_PROGRESS : 0;
1313
1314         /* FIXME -- We support only default key */
1315         hdr->key_count = 1;
1316
1317         return 0;
1318 }
1319
1320 static int sb_postfill_image_header(struct sb_image_ctx *ictx)
1321 {
1322         struct sb_boot_image_header *hdr = &ictx->payload;
1323         struct sb_section_ctx *sctx = ictx->sect_head;
1324         uint32_t kd_size, sections_blocks;
1325         EVP_MD_CTX md_ctx;
1326
1327         /* The main SB header size in blocks. */
1328         hdr->image_blocks = hdr->header_blocks;
1329
1330         /* Size of the key dictionary, which has single zero entry. */
1331         kd_size = hdr->key_count * sizeof(struct sb_key_dictionary_key);
1332         hdr->image_blocks += kd_size / SB_BLOCK_SIZE;
1333
1334         /* Now count the payloads. */
1335         hdr->section_count = ictx->sect_count;
1336         while (sctx) {
1337                 hdr->image_blocks += sctx->size / SB_BLOCK_SIZE;
1338                 sctx = sctx->sect;
1339         }
1340
1341         if (!ictx->sect_boot_found) {
1342                 fprintf(stderr, "ERR: No bootable section selected!\n");
1343                 return -EINVAL;
1344         }
1345         hdr->first_boot_section_id = ictx->sect_boot;
1346
1347         /* The n * SB section size in blocks. */
1348         sections_blocks = hdr->section_count * hdr->section_header_size;
1349         hdr->image_blocks += sections_blocks;
1350
1351         /* Key dictionary offset. */
1352         hdr->key_dictionary_block = hdr->header_blocks + sections_blocks;
1353
1354         /* Digest of the whole image. */
1355         hdr->image_blocks += 2;
1356
1357         /* Pointer past the dictionary. */
1358         hdr->first_boot_tag_block =
1359                 hdr->key_dictionary_block + kd_size / SB_BLOCK_SIZE;
1360
1361         /* Compute header digest. */
1362         EVP_MD_CTX_init(&md_ctx);
1363
1364         EVP_DigestInit(&md_ctx, EVP_sha1());
1365         EVP_DigestUpdate(&md_ctx, hdr->signature1,
1366                          sizeof(struct sb_boot_image_header) -
1367                          sizeof(hdr->digest));
1368         EVP_DigestFinal(&md_ctx, hdr->digest, NULL);
1369
1370         return 0;
1371 }
1372
1373 static int sb_fixup_sections_and_tags(struct sb_image_ctx *ictx)
1374 {
1375         /* Fixup the placement of sections. */
1376         struct sb_boot_image_header *ihdr = &ictx->payload;
1377         struct sb_section_ctx *sctx = ictx->sect_head;
1378         struct sb_sections_header *shdr;
1379         struct sb_cmd_ctx *cctx;
1380         struct sb_command *ccmd;
1381         uint32_t offset = ihdr->first_boot_tag_block;
1382
1383         while (sctx) {
1384                 shdr = &sctx->payload;
1385
1386                 /* Fill in the section TAG offset. */
1387                 shdr->section_offset = offset + 1;
1388                 offset += shdr->section_size;
1389
1390                 /* Section length is measured from the TAG block. */
1391                 shdr->section_size--;
1392
1393                 /* Fixup the TAG command. */
1394                 cctx = sctx->cmd_head;
1395                 while (cctx) {
1396                         ccmd = &cctx->payload;
1397                         if (ccmd->header.tag == ROM_TAG_CMD) {
1398                                 ccmd->tag.section_number = shdr->section_number;
1399                                 ccmd->tag.section_length = shdr->section_size;
1400                                 ccmd->tag.section_flags = shdr->section_flags;
1401                         }
1402
1403                         /* Update the command checksum. */
1404                         ccmd->header.checksum = sb_command_checksum(ccmd);
1405
1406                         cctx = cctx->cmd;
1407                 }
1408
1409                 sctx = sctx->sect;
1410         }
1411
1412         return 0;
1413 }
1414
1415 static int sb_parse_line(struct sb_image_ctx *ictx, struct sb_cmd_list *cmd)
1416 {
1417         char *tok;
1418         char *line = cmd->cmd;
1419         char *rptr = NULL;
1420         int ret;
1421
1422         /* Analyze the identifier on this line first. */
1423         tok = strtok_r(line, " ", &rptr);
1424         if (!tok || (strlen(tok) == 0)) {
1425                 fprintf(stderr, "#%i ERR: Invalid line!\n", cmd->lineno);
1426                 return -EINVAL;
1427         }
1428
1429         cmd->cmd = rptr;
1430
1431         /* set DISPLAY_PROGRESS flag */
1432         if (!strcmp(tok, "DISPLAYPROGRESS")) {
1433                 ictx->display_progress = 1;
1434                 return 0;
1435         }
1436
1437         /* DCD */
1438         if (!strcmp(tok, "DCD")) {
1439                 ictx->in_section = 0;
1440                 ictx->in_dcd = 1;
1441                 sb_build_dcd(ictx, cmd);
1442                 return 0;
1443         }
1444
1445         /* Section */
1446         if (!strcmp(tok, "SECTION")) {
1447                 ictx->in_section = 1;
1448                 ictx->in_dcd = 0;
1449                 sb_build_section(ictx, cmd);
1450                 return 0;
1451         }
1452
1453         if (!ictx->in_section && !ictx->in_dcd) {
1454                 fprintf(stderr, "#%i ERR: Data outside of a section!\n",
1455                         cmd->lineno);
1456                 return -EINVAL;
1457         }
1458
1459         if (ictx->in_section) {
1460                 /* Section commands */
1461                 if (!strcmp(tok, "NOP")) {
1462                         ret = sb_build_command_nop(ictx);
1463                 } else if (!strcmp(tok, "TAG")) {
1464                         ret = sb_build_command_tag(ictx, cmd);
1465                 } else if (!strcmp(tok, "LOAD")) {
1466                         ret = sb_build_command_load(ictx, cmd);
1467                 } else if (!strcmp(tok, "FILL")) {
1468                         ret = sb_build_command_fill(ictx, cmd);
1469                 } else if (!strcmp(tok, "JUMP")) {
1470                         ret = sb_build_command_jump(ictx, cmd);
1471                 } else if (!strcmp(tok, "CALL")) {
1472                         ret = sb_build_command_call(ictx, cmd);
1473                 } else if (!strcmp(tok, "MODE")) {
1474                         ret = sb_build_command_mode(ictx, cmd);
1475                 } else {
1476                         fprintf(stderr,
1477                                 "#%i ERR: Unsupported instruction '%s'!\n",
1478                                 cmd->lineno, tok);
1479                         return -ENOTSUP;
1480                 }
1481         } else if (ictx->in_dcd) {
1482                 char *lptr;
1483                 uint32_t ilen = '1';
1484
1485                 tok = strtok_r(tok, ".", &lptr);
1486                 if (!tok || (strlen(tok) == 0) || (lptr && strlen(lptr) != 1)) {
1487                         fprintf(stderr, "#%i ERR: Invalid line!\n",
1488                                 cmd->lineno);
1489                         return -EINVAL;
1490                 }
1491
1492                 if (lptr &&
1493                     (lptr[0] != '1' && lptr[0] != '2' && lptr[0] != '4')) {
1494                         fprintf(stderr, "#%i ERR: Invalid instruction width!\n",
1495                                 cmd->lineno);
1496                         return -EINVAL;
1497                 }
1498
1499                 if (lptr)
1500                         ilen = lptr[0] - '1';
1501
1502                 /* DCD commands */
1503                 if (!strcmp(tok, "WRITE")) {
1504                         ret = sb_build_dcd_block(ictx, cmd,
1505                                                  SB_DCD_WRITE | ilen);
1506                 } else if (!strcmp(tok, "ANDC")) {
1507                         ret = sb_build_dcd_block(ictx, cmd,
1508                                                  SB_DCD_ANDC | ilen);
1509                 } else if (!strcmp(tok, "ORR")) {
1510                         ret = sb_build_dcd_block(ictx, cmd,
1511                                                  SB_DCD_ORR | ilen);
1512                 } else if (!strcmp(tok, "EQZ")) {
1513                         ret = sb_build_dcd_block(ictx, cmd,
1514                                                  SB_DCD_CHK_EQZ | ilen);
1515                 } else if (!strcmp(tok, "EQ")) {
1516                         ret = sb_build_dcd_block(ictx, cmd,
1517                                                  SB_DCD_CHK_EQ | ilen);
1518                 } else if (!strcmp(tok, "NEQ")) {
1519                         ret = sb_build_dcd_block(ictx, cmd,
1520                                                  SB_DCD_CHK_NEQ | ilen);
1521                 } else if (!strcmp(tok, "NEZ")) {
1522                         ret = sb_build_dcd_block(ictx, cmd,
1523                                                  SB_DCD_CHK_NEZ | ilen);
1524                 } else if (!strcmp(tok, "NOOP")) {
1525                         ret = sb_build_dcd_block(ictx, cmd, SB_DCD_NOOP);
1526                 } else {
1527                         fprintf(stderr,
1528                                 "#%i ERR: Unsupported instruction '%s'!\n",
1529                                 cmd->lineno, tok);
1530                         return -ENOTSUP;
1531                 }
1532         } else {
1533                 fprintf(stderr, "#%i ERR: Unsupported instruction '%s'!\n",
1534                         cmd->lineno, tok);
1535                 return -ENOTSUP;
1536         }
1537
1538         /*
1539          * Here we have at least one section with one command, otherwise we
1540          * would have failed already higher above.
1541          *
1542          * FIXME -- should the updating happen here ?
1543          */
1544         if (ictx->in_section && !ret) {
1545                 ictx->sect_tail->size += ictx->sect_tail->cmd_tail->size;
1546                 ictx->sect_tail->payload.section_size =
1547                         ictx->sect_tail->size / SB_BLOCK_SIZE;
1548         }
1549
1550         return ret;
1551 }
1552
1553 static int sb_load_cmdfile(struct sb_image_ctx *ictx)
1554 {
1555         struct sb_cmd_list cmd;
1556         int lineno = 1;
1557         FILE *fp;
1558         char *line = NULL;
1559         ssize_t rlen;
1560         size_t len;
1561
1562         fp = fopen(ictx->cfg_filename, "r");
1563         if (!fp)
1564                 goto err_file;
1565
1566         while ((rlen = getline(&line, &len, fp)) > 0) {
1567                 memset(&cmd, 0, sizeof(cmd));
1568
1569                 /* Strip the trailing newline. */
1570                 line[rlen - 1] = '\0';
1571
1572                 cmd.cmd = line;
1573                 cmd.len = rlen;
1574                 cmd.lineno = lineno++;
1575
1576                 sb_parse_line(ictx, &cmd);
1577         }
1578
1579         free(line);
1580
1581         fclose(fp);
1582
1583         return 0;
1584
1585 err_file:
1586         fclose(fp);
1587         fprintf(stderr, "ERR: Failed to load file \"%s\"\n",
1588                 ictx->cfg_filename);
1589         return -EINVAL;
1590 }
1591
1592 static int sb_build_tree_from_cfg(struct sb_image_ctx *ictx)
1593 {
1594         int ret;
1595
1596         ret = sb_load_cmdfile(ictx);
1597         if (ret)
1598                 return ret;
1599
1600         ret = sb_prefill_image_header(ictx);
1601         if (ret)
1602                 return ret;
1603
1604         ret = sb_postfill_image_header(ictx);
1605         if (ret)
1606                 return ret;
1607
1608         ret = sb_fixup_sections_and_tags(ictx);
1609         if (ret)
1610                 return ret;
1611
1612         return 0;
1613 }
1614
1615 static int sb_verify_image_header(struct sb_image_ctx *ictx,
1616                                   FILE *fp, long fsize)
1617 {
1618         /* Verify static fields in the image header. */
1619         struct sb_boot_image_header *hdr = &ictx->payload;
1620         const char *stat[2] = { "[PASS]", "[FAIL]" };
1621         struct tm tm;
1622         int sz, ret = 0;
1623         unsigned char digest[20];
1624         EVP_MD_CTX md_ctx;
1625         unsigned long size;
1626
1627         /* Start image-wide crypto. */
1628         EVP_MD_CTX_init(&ictx->md_ctx);
1629         EVP_DigestInit(&ictx->md_ctx, EVP_sha1());
1630
1631         soprintf(ictx, "---------- Verifying SB Image Header ----------\n");
1632
1633         size = fread(&ictx->payload, 1, sizeof(ictx->payload), fp);
1634         if (size != sizeof(ictx->payload)) {
1635                 fprintf(stderr, "ERR: SB image header too short!\n");
1636                 return -EINVAL;
1637         }
1638
1639         /* Compute header digest. */
1640         EVP_MD_CTX_init(&md_ctx);
1641         EVP_DigestInit(&md_ctx, EVP_sha1());
1642         EVP_DigestUpdate(&md_ctx, hdr->signature1,
1643                          sizeof(struct sb_boot_image_header) -
1644                          sizeof(hdr->digest));
1645         EVP_DigestFinal(&md_ctx, digest, NULL);
1646
1647         sb_aes_init(ictx, NULL, 1);
1648         sb_encrypt_sb_header(ictx);
1649
1650         if (memcmp(digest, hdr->digest, 20))
1651                 ret = -EINVAL;
1652         soprintf(ictx, "%s Image header checksum:        %s\n", stat[!!ret],
1653                  ret ? "BAD" : "OK");
1654         if (ret)
1655                 return ret;
1656
1657         if (memcmp(hdr->signature1, "STMP", 4) ||
1658             memcmp(hdr->signature2, "sgtl", 4))
1659                 ret = -EINVAL;
1660         soprintf(ictx, "%s Signatures:                   '%.4s' '%.4s'\n",
1661                  stat[!!ret], hdr->signature1, hdr->signature2);
1662         if (ret)
1663                 return ret;
1664
1665         if ((hdr->major_version != SB_VERSION_MAJOR) ||
1666             ((hdr->minor_version != 1) && (hdr->minor_version != 2)))
1667                 ret = -EINVAL;
1668         soprintf(ictx, "%s Image version:                v%i.%i\n", stat[!!ret],
1669                  hdr->major_version, hdr->minor_version);
1670         if (ret)
1671                 return ret;
1672
1673         ret = sb_get_time(hdr->timestamp_us / 1000000, &tm);
1674         soprintf(ictx,
1675                  "%s Creation time:                %02i:%02i:%02i %02i/%02i/%04i\n",
1676                  stat[!!ret], tm.tm_hour, tm.tm_min, tm.tm_sec,
1677                  tm.tm_mday, tm.tm_mon, tm.tm_year + 2000);
1678         if (ret)
1679                 return ret;
1680
1681         soprintf(ictx, "%s Product version:              %x.%x.%x\n", stat[0],
1682                  ntohs(hdr->product_version.major),
1683                  ntohs(hdr->product_version.minor),
1684                  ntohs(hdr->product_version.revision));
1685         soprintf(ictx, "%s Component version:            %x.%x.%x\n", stat[0],
1686                  ntohs(hdr->component_version.major),
1687                  ntohs(hdr->component_version.minor),
1688                  ntohs(hdr->component_version.revision));
1689
1690         if (hdr->flags & ~SB_IMAGE_FLAGS_MASK)
1691                 ret = -EINVAL;
1692         soprintf(ictx, "%s Image flags:                  %s\n", stat[!!ret],
1693                  hdr->flags & SB_IMAGE_FLAG_DISPLAY_PROGRESS ?
1694                  "Display_progress" : "");
1695         if (ret)
1696                 return ret;
1697
1698         if (hdr->drive_tag != 0)
1699                 ret = -EINVAL;
1700         soprintf(ictx, "%s Drive tag:                    %i\n", stat[!!ret],
1701                  hdr->drive_tag);
1702         if (ret)
1703                 return ret;
1704
1705         sz = sizeof(struct sb_boot_image_header) / SB_BLOCK_SIZE;
1706         if (hdr->header_blocks != sz)
1707                 ret = -EINVAL;
1708         soprintf(ictx, "%s Image header size (blocks):   %i\n", stat[!!ret],
1709                  hdr->header_blocks);
1710         if (ret)
1711                 return ret;
1712
1713         sz = sizeof(struct sb_sections_header) / SB_BLOCK_SIZE;
1714         if (hdr->section_header_size != sz)
1715                 ret = -EINVAL;
1716         soprintf(ictx, "%s Section header size (blocks): %i\n", stat[!!ret],
1717                  hdr->section_header_size);
1718         if (ret)
1719                 return ret;
1720
1721         soprintf(ictx, "%s Sections count:               %i\n", stat[!!ret],
1722                  hdr->section_count);
1723         soprintf(ictx, "%s First bootable section        %i\n", stat[!!ret],
1724                  hdr->first_boot_section_id);
1725
1726         if (hdr->image_blocks != fsize / SB_BLOCK_SIZE)
1727                 ret = -EINVAL;
1728         soprintf(ictx, "%s Image size (blocks):          %i\n", stat[!!ret],
1729                  hdr->image_blocks);
1730         if (ret)
1731                 return ret;
1732
1733         sz = hdr->header_blocks + hdr->section_header_size * hdr->section_count;
1734         if (hdr->key_dictionary_block != sz)
1735                 ret = -EINVAL;
1736         soprintf(ictx, "%s Key dict offset (blocks):     %i\n", stat[!!ret],
1737                  hdr->key_dictionary_block);
1738         if (ret)
1739                 return ret;
1740
1741         if (hdr->key_count != 1)
1742                 ret = -EINVAL;
1743         soprintf(ictx, "%s Number of encryption keys:    %i\n", stat[!!ret],
1744                  hdr->key_count);
1745         if (ret)
1746                 return ret;
1747
1748         sz = hdr->header_blocks + hdr->section_header_size * hdr->section_count;
1749         sz += hdr->key_count *
1750                 sizeof(struct sb_key_dictionary_key) / SB_BLOCK_SIZE;
1751         if (hdr->first_boot_tag_block != (unsigned)sz)
1752                 ret = -EINVAL;
1753         soprintf(ictx, "%s First TAG block (blocks):     %i\n", stat[!!ret],
1754                  hdr->first_boot_tag_block);
1755         if (ret)
1756                 return ret;
1757
1758         return 0;
1759 }
1760
1761 static void sb_decrypt_tag(struct sb_image_ctx *ictx,
1762                 struct sb_cmd_ctx *cctx)
1763 {
1764         EVP_MD_CTX *md_ctx = &ictx->md_ctx;
1765         struct sb_command *cmd = &cctx->payload;
1766
1767         sb_aes_crypt(ictx, (uint8_t *)&cctx->c_payload,
1768                      (uint8_t *)&cctx->payload, sizeof(*cmd));
1769         EVP_DigestUpdate(md_ctx, &cctx->c_payload, sizeof(*cmd));
1770 }
1771
1772 static int sb_verify_command(struct sb_image_ctx *ictx,
1773                              struct sb_cmd_ctx *cctx, FILE *fp,
1774                              unsigned long *tsize)
1775 {
1776         struct sb_command *ccmd = &cctx->payload;
1777         unsigned long size, asize;
1778         char *csum, *flag = "";
1779         int ret;
1780         unsigned int i;
1781         uint8_t csn, csc = ccmd->header.checksum;
1782         ccmd->header.checksum = 0x5a;
1783         csn = sb_command_checksum(ccmd);
1784         ccmd->header.checksum = csc;
1785
1786         if (csc == csn)
1787                 ret = 0;
1788         else
1789                 ret = -EINVAL;
1790         csum = ret ? "checksum BAD" : "checksum OK";
1791
1792         switch (ccmd->header.tag) {
1793         case ROM_NOP_CMD:
1794                 soprintf(ictx, " NOOP # %s\n", csum);
1795                 return ret;
1796         case ROM_TAG_CMD:
1797                 if (ccmd->header.flags & ROM_TAG_CMD_FLAG_ROM_LAST_TAG)
1798                         flag = "LAST";
1799                 soprintf(ictx, " TAG %s # %s\n", flag, csum);
1800                 sb_aes_reinit(ictx, 0);
1801                 return ret;
1802         case ROM_LOAD_CMD:
1803                 soprintf(ictx, " LOAD addr=0x%08x length=0x%08x # %s\n",
1804                          ccmd->load.address, ccmd->load.count, csum);
1805
1806                 cctx->length = ccmd->load.count;
1807                 asize = roundup(cctx->length, SB_BLOCK_SIZE);
1808                 cctx->data = malloc(asize);
1809                 if (!cctx->data)
1810                         return -ENOMEM;
1811
1812                 size = fread(cctx->data, 1, asize, fp);
1813                 if (size != asize) {
1814                         fprintf(stderr,
1815                                 "ERR: SB LOAD command payload too short!\n");
1816                         return -EINVAL;
1817                 }
1818
1819                 *tsize += size;
1820
1821                 EVP_DigestUpdate(&ictx->md_ctx, cctx->data, asize);
1822                 sb_aes_crypt(ictx, cctx->data, cctx->data, asize);
1823
1824                 if (ccmd->load.crc32 != pbl_crc32(0,
1825                                                   (const char *)cctx->data,
1826                                                   asize)) {
1827                         fprintf(stderr,
1828                                 "ERR: SB LOAD command payload CRC32 invalid!\n");
1829                         return -EINVAL;
1830                 }
1831                 return 0;
1832         case ROM_FILL_CMD:
1833                 soprintf(ictx,
1834                          " FILL addr=0x%08x length=0x%08x pattern=0x%08x # %s\n",
1835                          ccmd->fill.address, ccmd->fill.count,
1836                          ccmd->fill.pattern, csum);
1837                 return 0;
1838         case ROM_JUMP_CMD:
1839                 if (ccmd->header.flags & ROM_JUMP_CMD_FLAG_HAB)
1840                         flag = " HAB";
1841                 soprintf(ictx,
1842                          " JUMP%s addr=0x%08x r0_arg=0x%08x # %s\n",
1843                          flag, ccmd->fill.address, ccmd->jump.argument, csum);
1844                 return 0;
1845         case ROM_CALL_CMD:
1846                 if (ccmd->header.flags & ROM_CALL_CMD_FLAG_HAB)
1847                         flag = " HAB";
1848                 soprintf(ictx,
1849                          " CALL%s addr=0x%08x r0_arg=0x%08x # %s\n",
1850                          flag, ccmd->fill.address, ccmd->jump.argument, csum);
1851                 return 0;
1852         case ROM_MODE_CMD:
1853                 for (i = 0; i < ARRAY_SIZE(modetable); i++) {
1854                         if (ccmd->mode.mode == modetable[i].mode) {
1855                                 soprintf(ictx, " MODE %s # %s\n",
1856                                          modetable[i].name, csum);
1857                                 break;
1858                         }
1859                 }
1860                 fprintf(stderr, " MODE !INVALID! # %s\n", csum);
1861                 return 0;
1862         }
1863
1864         return ret;
1865 }
1866
1867 static int sb_verify_commands(struct sb_image_ctx *ictx,
1868                               struct sb_section_ctx *sctx, FILE *fp)
1869 {
1870         unsigned long size, tsize = 0;
1871         struct sb_cmd_ctx *cctx;
1872         int ret;
1873
1874         sb_aes_reinit(ictx, 0);
1875
1876         while (tsize < sctx->size) {
1877                 cctx = calloc(1, sizeof(*cctx));
1878                 if (!cctx)
1879                         return -ENOMEM;
1880                 if (!sctx->cmd_head) {
1881                         sctx->cmd_head = cctx;
1882                         sctx->cmd_tail = cctx;
1883                 } else {
1884                         sctx->cmd_tail->cmd = cctx;
1885                         sctx->cmd_tail = cctx;
1886                 }
1887
1888                 size = fread(&cctx->c_payload, 1, sizeof(cctx->c_payload), fp);
1889                 if (size != sizeof(cctx->c_payload)) {
1890                         fprintf(stderr, "ERR: SB command header too short!\n");
1891                         return -EINVAL;
1892                 }
1893
1894                 tsize += size;
1895
1896                 sb_decrypt_tag(ictx, cctx);
1897
1898                 ret = sb_verify_command(ictx, cctx, fp, &tsize);
1899                 if (ret)
1900                         return -EINVAL;
1901         }
1902
1903         return 0;
1904 }
1905
1906 static int sb_verify_sections_cmds(struct sb_image_ctx *ictx, FILE *fp)
1907 {
1908         struct sb_boot_image_header *hdr = &ictx->payload;
1909         struct sb_sections_header *shdr;
1910         unsigned int i;
1911         int ret;
1912         struct sb_section_ctx *sctx;
1913         unsigned long size;
1914         char *bootable = "";
1915
1916         soprintf(ictx, "----- Verifying  SB Sections and Commands -----\n");
1917
1918         for (i = 0; i < hdr->section_count; i++) {
1919                 sctx = calloc(1, sizeof(*sctx));
1920                 if (!sctx)
1921                         return -ENOMEM;
1922                 if (!ictx->sect_head) {
1923                         ictx->sect_head = sctx;
1924                         ictx->sect_tail = sctx;
1925                 } else {
1926                         ictx->sect_tail->sect = sctx;
1927                         ictx->sect_tail = sctx;
1928                 }
1929
1930                 size = fread(&sctx->payload, 1, sizeof(sctx->payload), fp);
1931                 if (size != sizeof(sctx->payload)) {
1932                         fprintf(stderr, "ERR: SB section header too short!\n");
1933                         return -EINVAL;
1934                 }
1935         }
1936
1937         size = fread(&ictx->sb_dict_key, 1, sizeof(ictx->sb_dict_key), fp);
1938         if (size != sizeof(ictx->sb_dict_key)) {
1939                 fprintf(stderr, "ERR: SB key dictionary too short!\n");
1940                 return -EINVAL;
1941         }
1942
1943         sb_encrypt_sb_sections_header(ictx);
1944         sb_aes_reinit(ictx, 0);
1945         sb_decrypt_key_dictionary_key(ictx);
1946
1947         sb_aes_reinit(ictx, 0);
1948
1949         sctx = ictx->sect_head;
1950         while (sctx) {
1951                 shdr = &sctx->payload;
1952
1953                 if (shdr->section_flags & SB_SECTION_FLAG_BOOTABLE) {
1954                         sctx->boot = 1;
1955                         bootable = " BOOTABLE";
1956                 }
1957
1958                 sctx->size = (shdr->section_size * SB_BLOCK_SIZE) +
1959                              sizeof(struct sb_command);
1960                 soprintf(ictx, "SECTION 0x%x%s # size = %i bytes\n",
1961                          shdr->section_number, bootable, sctx->size);
1962
1963                 if (shdr->section_flags & ~SB_SECTION_FLAG_BOOTABLE)
1964                         fprintf(stderr, " WARN: Unknown section flag(s) %08x\n",
1965                                 shdr->section_flags);
1966
1967                 if ((shdr->section_flags & SB_SECTION_FLAG_BOOTABLE) &&
1968                     (hdr->first_boot_section_id != shdr->section_number)) {
1969                         fprintf(stderr,
1970                                 " WARN: Bootable section does ID not match image header ID!\n");
1971                 }
1972
1973                 ret = sb_verify_commands(ictx, sctx, fp);
1974                 if (ret)
1975                         return ret;
1976
1977                 sctx = sctx->sect;
1978         }
1979
1980         /*
1981          * FIXME IDEA:
1982          * check if the first TAG command is at sctx->section_offset
1983          */
1984         return 0;
1985 }
1986
1987 static int sb_verify_image_end(struct sb_image_ctx *ictx,
1988                                FILE *fp, off_t filesz)
1989 {
1990         uint8_t digest[32];
1991         unsigned long size;
1992         off_t pos;
1993         int ret;
1994
1995         soprintf(ictx, "------------- Verifying image end -------------\n");
1996
1997         size = fread(digest, 1, sizeof(digest), fp);
1998         if (size != sizeof(digest)) {
1999                 fprintf(stderr, "ERR: SB key dictionary too short!\n");
2000                 return -EINVAL;
2001         }
2002
2003         pos = ftell(fp);
2004         if (pos != filesz) {
2005                 fprintf(stderr, "ERR: Trailing data past the image!\n");
2006                 return -EINVAL;
2007         }
2008
2009         /* Check the image digest. */
2010         EVP_DigestFinal(&ictx->md_ctx, ictx->digest, NULL);
2011
2012         /* Decrypt the image digest from the input image. */
2013         sb_aes_reinit(ictx, 0);
2014         sb_aes_crypt(ictx, digest, digest, sizeof(digest));
2015
2016         /* Check all of 20 bytes of the SHA1 hash. */
2017         ret = memcmp(digest, ictx->digest, 20) ? -EINVAL : 0;
2018
2019         if (ret)
2020                 soprintf(ictx, "[FAIL] Full-image checksum:          BAD\n");
2021         else
2022                 soprintf(ictx, "[PASS] Full-image checksum:          OK\n");
2023
2024         return ret;
2025 }
2026
2027
2028 static int sb_build_tree_from_img(struct sb_image_ctx *ictx)
2029 {
2030         long filesize;
2031         int ret;
2032         FILE *fp;
2033
2034         if (!ictx->input_filename) {
2035                 fprintf(stderr, "ERR: Missing filename!\n");
2036                 return -EINVAL;
2037         }
2038
2039         fp = fopen(ictx->input_filename, "r");
2040         if (!fp)
2041                 goto err_open;
2042
2043         ret = fseek(fp, 0, SEEK_END);
2044         if (ret < 0)
2045                 goto err_file;
2046
2047         filesize = ftell(fp);
2048         if (filesize < 0)
2049                 goto err_file;
2050
2051         ret = fseek(fp, 0, SEEK_SET);
2052         if (ret < 0)
2053                 goto err_file;
2054
2055         if (filesize < (signed)sizeof(ictx->payload)) {
2056                 fprintf(stderr, "ERR: File too short!\n");
2057                 goto err_file;
2058         }
2059
2060         if (filesize & (SB_BLOCK_SIZE - 1)) {
2061                 fprintf(stderr, "ERR: The file is not aligned!\n");
2062                 goto err_file;
2063         }
2064
2065         /* Load and verify image header */
2066         ret = sb_verify_image_header(ictx, fp, filesize);
2067         if (ret)
2068                 goto err_verify;
2069
2070         /* Load and verify sections and commands */
2071         ret = sb_verify_sections_cmds(ictx, fp);
2072         if (ret)
2073                 goto err_verify;
2074
2075         ret = sb_verify_image_end(ictx, fp, filesize);
2076         if (ret)
2077                 goto err_verify;
2078
2079         ret = 0;
2080
2081 err_verify:
2082         soprintf(ictx, "-------------------- Result -------------------\n");
2083         soprintf(ictx, "Verification %s\n", ret ? "FAILED" : "PASSED");
2084
2085         /* Stop the encryption session. */
2086         sb_aes_deinit(&ictx->cipher_ctx);
2087
2088         fclose(fp);
2089         return ret;
2090
2091 err_file:
2092         fclose(fp);
2093 err_open:
2094         fprintf(stderr, "ERR: Failed to load file \"%s\"\n",
2095                 ictx->input_filename);
2096         return -EINVAL;
2097 }
2098
2099 static void sb_free_image(struct sb_image_ctx *ictx)
2100 {
2101         struct sb_section_ctx *sctx = ictx->sect_head, *s_head;
2102         struct sb_dcd_ctx *dctx = ictx->dcd_head, *d_head;
2103         struct sb_cmd_ctx *cctx, *c_head;
2104
2105         while (sctx) {
2106                 s_head = sctx;
2107                 c_head = sctx->cmd_head;
2108
2109                 while (c_head) {
2110                         cctx = c_head;
2111                         c_head = c_head->cmd;
2112                         if (cctx->data)
2113                                 free(cctx->data);
2114                         free(cctx);
2115                 }
2116
2117                 sctx = sctx->sect;
2118                 free(s_head);
2119         }
2120
2121         while (dctx) {
2122                 d_head = dctx;
2123                 dctx = dctx->dcd;
2124                 free(d_head->payload);
2125                 free(d_head);
2126         }
2127 }
2128
2129 /*
2130  * MXSSB-MKIMAGE glue code.
2131  */
2132 static int mxsimage_check_image_types(uint8_t type)
2133 {
2134         if (type == IH_TYPE_MXSIMAGE)
2135                 return EXIT_SUCCESS;
2136         else
2137                 return EXIT_FAILURE;
2138 }
2139
2140 static void mxsimage_set_header(void *ptr, struct stat *sbuf, int ifd,
2141                                 struct image_tool_params *params)
2142 {
2143 }
2144
2145 int mxsimage_check_params(struct image_tool_params *params)
2146 {
2147         if (!params)
2148                 return -1;
2149         if (!strlen(params->imagename)) {
2150                 fprintf(stderr,
2151                         "Error: %s - Configuration file not specified, it is needed for mxsimage generation\n",
2152                         params->cmdname);
2153                 return -1;
2154         }
2155
2156         /*
2157          * Check parameters:
2158          * XIP is not allowed and verify that incompatible
2159          * parameters are not sent at the same time
2160          * For example, if list is required a data image must not be provided
2161          */
2162         return  (params->dflag && (params->fflag || params->lflag)) ||
2163                 (params->fflag && (params->dflag || params->lflag)) ||
2164                 (params->lflag && (params->dflag || params->fflag)) ||
2165                 (params->xflag) || !(strlen(params->imagename));
2166 }
2167
2168 static int mxsimage_verify_print_header(char *file, int silent)
2169 {
2170         int ret;
2171         struct sb_image_ctx ctx;
2172
2173         memset(&ctx, 0, sizeof(ctx));
2174
2175         ctx.input_filename = file;
2176         ctx.silent_dump = silent;
2177
2178         ret = sb_build_tree_from_img(&ctx);
2179         sb_free_image(&ctx);
2180
2181         return ret;
2182 }
2183
2184 char *imagefile;
2185 static int mxsimage_verify_header(unsigned char *ptr, int image_size,
2186                         struct image_tool_params *params)
2187 {
2188         struct sb_boot_image_header *hdr;
2189
2190         if (!ptr)
2191                 return -EINVAL;
2192
2193         hdr = (struct sb_boot_image_header *)ptr;
2194
2195         /*
2196          * Check if the header contains the MXS image signatures,
2197          * if so, do a full-image verification.
2198          */
2199         if (memcmp(hdr->signature1, "STMP", 4) ||
2200             memcmp(hdr->signature2, "sgtl", 4))
2201                 return -EINVAL;
2202
2203         imagefile = params->imagefile;
2204
2205         return mxsimage_verify_print_header(params->imagefile, 1);
2206 }
2207
2208 static void mxsimage_print_header(const void *hdr)
2209 {
2210         if (imagefile)
2211                 mxsimage_verify_print_header(imagefile, 0);
2212 }
2213
2214 static int sb_build_image(struct sb_image_ctx *ictx,
2215                           struct image_type_params *tparams)
2216 {
2217         struct sb_boot_image_header *sb_header = &ictx->payload;
2218         struct sb_section_ctx *sctx;
2219         struct sb_cmd_ctx *cctx;
2220         struct sb_command *ccmd;
2221         struct sb_key_dictionary_key *sb_dict_key = &ictx->sb_dict_key;
2222
2223         uint8_t *image, *iptr;
2224
2225         /* Calculate image size. */
2226         uint32_t size = sizeof(*sb_header) +
2227                 ictx->sect_count * sizeof(struct sb_sections_header) +
2228                 sizeof(*sb_dict_key) + sizeof(ictx->digest);
2229
2230         sctx = ictx->sect_head;
2231         while (sctx) {
2232                 size += sctx->size;
2233                 sctx = sctx->sect;
2234         };
2235
2236         image = malloc(size);
2237         if (!image)
2238                 return -ENOMEM;
2239         iptr = image;
2240
2241         memcpy(iptr, sb_header, sizeof(*sb_header));
2242         iptr += sizeof(*sb_header);
2243
2244         sctx = ictx->sect_head;
2245         while (sctx) {
2246                 memcpy(iptr, &sctx->payload, sizeof(struct sb_sections_header));
2247                 iptr += sizeof(struct sb_sections_header);
2248                 sctx = sctx->sect;
2249         };
2250
2251         memcpy(iptr, sb_dict_key, sizeof(*sb_dict_key));
2252         iptr += sizeof(*sb_dict_key);
2253
2254         sctx = ictx->sect_head;
2255         while (sctx) {
2256                 cctx = sctx->cmd_head;
2257                 while (cctx) {
2258                         ccmd = &cctx->payload;
2259
2260                         memcpy(iptr, &cctx->c_payload, sizeof(cctx->payload));
2261                         iptr += sizeof(cctx->payload);
2262
2263                         if (ccmd->header.tag == ROM_LOAD_CMD) {
2264                                 memcpy(iptr, cctx->data, cctx->length);
2265                                 iptr += cctx->length;
2266                         }
2267
2268                         cctx = cctx->cmd;
2269                 }
2270
2271                 sctx = sctx->sect;
2272         };
2273
2274         memcpy(iptr, ictx->digest, sizeof(ictx->digest));
2275         iptr += sizeof(ictx->digest);
2276
2277         /* Configure the mkimage */
2278         tparams->hdr = image;
2279         tparams->header_size = size;
2280
2281         return 0;
2282 }
2283
2284 static int mxsimage_generate(struct image_tool_params *params,
2285         struct image_type_params *tparams)
2286 {
2287         int ret;
2288         struct sb_image_ctx ctx;
2289
2290         /* Do not copy the U-Boot image! */
2291         params->skipcpy = 1;
2292
2293         memset(&ctx, 0, sizeof(ctx));
2294
2295         ctx.cfg_filename = params->imagename;
2296         ctx.output_filename = params->imagefile;
2297
2298         ret = sb_build_tree_from_cfg(&ctx);
2299         if (ret)
2300                 goto fail;
2301
2302         ret = sb_encrypt_image(&ctx);
2303         if (!ret)
2304                 ret = sb_build_image(&ctx, tparams);
2305
2306 fail:
2307         sb_free_image(&ctx);
2308
2309         return ret;
2310 }
2311
2312 /*
2313  * mxsimage parameters
2314  */
2315 U_BOOT_IMAGE_TYPE(
2316         mxsimage,
2317         "Freescale MXS Boot Image support",
2318         0,
2319         NULL,
2320         mxsimage_check_params,
2321         mxsimage_verify_header,
2322         mxsimage_print_header,
2323         mxsimage_set_header,
2324         NULL,
2325         mxsimage_check_image_types,
2326         NULL,
2327         mxsimage_generate
2328 );
2329 #endif