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