source: trunk/tools/firmware-utils/src/mkcsysimg.c @ 8352

Last change on this file since 8352 was 8352, checked in by juhosg, 9 years ago

remove case sensitivity from the board name checking

File size: 20.3 KB
Line 
1/*
2 *  $Id$
3 *
4 *  Copyright (C) 2007 Gabor Juhos <juhosg@freemail.hu>
5 *
6 *  This program was based on the code found in various Linux
7 *  source tarballs released by Edimax for it's devices.
8 *  Original author: David Hsu <davidhsu@realtek.com.tw>
9 *
10 *  This program is free software; you can redistribute it and/or
11 *  modify it under the terms of the GNU General Public License
12 *  as published by the Free Software Foundation; either version 2
13 *  of the License, or (at your option) any later version.
14 *
15 *  This program is distributed in the hope that it will be useful,
16 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 *  GNU General Public License for more details.
19 *
20 *  You should have received a copy of the GNU General Public License
21 *  along with this program; if not, write to the
22 *  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23 *  Boston, MA  02110-1301, USA.
24 */
25
26#include <stdio.h>
27#include <stdlib.h>
28#include <stdint.h>
29#include <string.h>
30#include <unistd.h>     /* for unlink() */
31#include <libgen.h>
32#include <getopt.h>     /* for getopt() */
33#include <stdarg.h>
34#include <errno.h>
35#include <sys/stat.h>
36#include <endian.h>     /* for __BYTE_ORDER */
37#if defined(__CYGWIN__)
38#  include <byteswap.h>
39#endif
40
41#include "csysimg.h"
42
43#if (__BYTE_ORDER == __LITTLE_ENDIAN)
44#  define HOST_TO_LE16(x)       (x)
45#  define HOST_TO_LE32(x)       (x)
46#  define LE16_TO_HOST(x)       (x)
47#  define LE32_TO_HOST(x)       (x)
48#else
49#  define HOST_TO_LE16(x)       bswap_16(x)
50#  define HOST_TO_LE32(x)       bswap_32(x)
51#  define LE16_TO_HOST(x)       bswap_16(x)
52#  define LE32_TO_HOST(x)       bswap_32(x)
53#endif
54
55#define ALIGN(x,y)      ((x)+((y)-1)) & ~((y)-1)
56
57#define MAX_NUM_BLOCKS  8
58#define MAX_ARG_COUNT   32
59#define MAX_ARG_LEN     1024
60#define FILE_BUF_LEN    (16*1024)
61#define CSYS_PADC       0xFF
62
63#define BLOCK_TYPE_BOOT 0
64#define BLOCK_TYPE_CONF 1
65#define BLOCK_TYPE_WEBP 2
66#define BLOCK_TYPE_CODE 3
67#define BLOCK_TYPE_XTRA 4
68
69
70struct csum_state{
71        int     size;
72        uint16_t val;
73        uint16_t tmp;
74        int     odd;
75};
76
77
78struct csys_block {
79        int             type;   /* type of the block */
80
81        int             need_file;
82        char            *file_name;     /* name of the file */
83        uint32_t        file_size;      /* length of the file */
84
85        uint32_t        size;
86        int             size_set;
87        uint8_t         padc;
88
89        uint32_t        size_hdr;
90        uint32_t        size_csum;
91        uint32_t        size_avail;
92
93        unsigned char   sig[SIG_LEN];
94        uint32_t        addr;
95        int             addr_set;
96        struct csum_state *css;
97};
98
99
100struct board_info {
101        char *model;
102        char *name;
103        uint32_t flash_size;
104
105        char sig_boot[SIG_LEN];
106        char sig_conf[SIG_LEN];
107        char sig_webp[SIG_LEN];
108
109        uint32_t boot_size;
110        uint32_t conf_size;
111        uint32_t webp_size;
112        uint32_t webp_size_max;
113        uint32_t code_size;
114
115        uint32_t addr_code;
116        uint32_t addr_webp;
117};
118
119#define BOARD(m, n, f, sigb, sigw, bs, cs, ws, ac, aw) {\
120        .model = m, .name = n, .flash_size = f<<20, \
121        .sig_boot = sigb, .sig_conf = SIG_CONF, .sig_webp = sigw, \
122        .boot_size = bs, .conf_size = cs, \
123        .webp_size = ws, .webp_size_max = 3*0x10000, \
124        .addr_code = ac, .addr_webp = aw \
125        }
126
127#define BOARD_ADM(m,n,f, sigw) BOARD(m,n,f, ADM_BOOT_SIG, sigw, \
128        ADM_BOOT_SIZE, ADM_CONF_SIZE, ADM_WEBP_SIZE, \
129        ADM_CODE_ADDR, ADM_WEBP_ADDR)
130
131
132/*
133 * Globals
134 */
135char *progname;
136char *ofname = NULL;
137int verblevel = 0;
138int invalid_causes_error = 1;
139int keep_invalid_images = 0;
140
141struct board_info *board = NULL;
142
143struct csys_block *boot_block = NULL;
144struct csys_block *conf_block = NULL;
145struct csys_block *webp_block = NULL;
146struct csys_block *code_block = NULL;
147
148struct csys_block blocks[MAX_NUM_BLOCKS];
149int num_blocks = 0;
150
151static struct board_info boards[] = {
152        /* The original Edimax products */
153        BOARD_ADM("BR-6104K", "Edimax BR-6104K", 2, SIG_BR6104K),
154        BOARD_ADM("BR-6104KP", "Edimax BR-6104KP", 2, SIG_BR6104KP),
155        BOARD_ADM("BR-6114WG", "Edimax BR-6114WG", 2, SIG_BR6114WG),
156        BOARD_ADM("BR-6524K", "Edimax BR-6524K", 2, SIG_BR6524K),
157        BOARD_ADM("BR-6524KP", "Edimax BR-6524KP", 2, SIG_BR6524KP),
158        BOARD_ADM("BR-6524WG", "Edimax BR-6524WG", 4, SIG_BR6524WG),
159        BOARD_ADM("BR-6524WP", "Edimax BR-6524WP", 4, SIG_BR6524WP),
160        BOARD_ADM("BR-6541K", "Edimax BR-6541K", 2, SIG_BR6541K),
161        BOARD_ADM("BR-6541KP", "Edimax BR-6541K", 2, SIG_BR6541KP),
162        BOARD_ADM("BR-6541WP", "Edimax BR-6541WP", 4, SIG_BR6541WP),
163        BOARD_ADM("EW-7207APg", "Edimax EW-7207APg", 2, SIG_EW7207APg),
164        BOARD_ADM("PS-1205UWg", "Edimax PS-1205UWg", 2, SIG_PS1205UWg),
165        BOARD_ADM("PS-3205U", "Edimax PS-3205U", 2, SIG_PS3205U),
166        BOARD_ADM("PS-3205UWg", "Edimax PS-3205UWg", 2, SIG_PS3205UWg),
167
168        /* Hawking products */
169        BOARD_ADM("H2BR4", "Hawking H2BR4", 2, SIG_H2BR4),
170        BOARD_ADM("H2WR54G", "Hawking H2WR54G", 4, SIG_H2WR54G),
171
172        /* Planet products */
173        BOARD_ADM("XRT-401D", "Planet XRT-401D", 2, SIG_XRT401D),
174        BOARD_ADM("XRT-402D", "Planet XRT-402D", 2, SIG_XRT402D),
175
176        {.model = NULL}
177};
178
179/*
180 * Message macros
181 */
182#define ERR(fmt, ...) do { \
183        fflush(0); \
184        fprintf(stderr, "[%s] *** error: " fmt "\n", progname, ## __VA_ARGS__ ); \
185} while (0)
186
187#define ERRS(fmt, ...) do { \
188        int save = errno; \
189        fflush(0); \
190        fprintf(stderr, "[%s] *** error: " fmt "\n", progname, ## __VA_ARGS__ \
191                , strerror(save)); \
192} while (0)
193
194#define WARN(fmt, ...) do { \
195        fprintf(stderr, "[%s] *** warning: " fmt "\n", progname, ## __VA_ARGS__ ); \
196} while (0)
197
198#define DBG(lev, fmt, ...) do { \
199        if (verblevel < lev) \
200                break;\
201        fprintf(stderr, "[%s] " fmt "\n", progname, ## __VA_ARGS__ ); \
202} while (0)
203
204#define ERR_FATAL               -1
205#define ERR_INVALID_IMAGE       -2
206
207void
208usage(int status)
209{
210        FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout;
211        struct board_info *board;
212
213        fprintf(stream, "Usage: %s [OPTIONS...] <file>\n", progname);
214        fprintf(stream,
215"\n"
216"Options:\n"
217"  -B <board>      create image for the board specified with <board>.\n"
218"                  valid <board> values:\n"
219        );
220        for (board = boards; board->model != NULL; board++){
221                fprintf(stream,
222"                  %-12s: %s\n",
223                 board->model, board->name);
224        };
225        fprintf(stream,
226"  -d              don't throw error on invalid images\n"
227"  -k              keep invalid images\n"
228"  -b <file>[:<len>[:<padc>]]\n"
229"                  add boot code to the image\n"
230"  -c <file>[:<len>[:<padc>]]\n"
231"                  add configuration settings to the image\n"
232"  -r <file>:[<addr>][:<len>[:<padc>]]\n"
233"                  add runtime code to the image\n"
234"  -w [<file>:[<addr>][:<len>[:<padc>]]]\n"
235"                  add webpages to the image\n"
236"  -x <file>[:<len>[:<padc>]]\n"
237"                  add extra data at the end of the image\n"
238"  -h              show this screen\n"
239"Parameters:\n"
240"  <file>          write output to the file <file>\n"
241        );
242
243        exit(status);
244}
245
246
247/*
248 * argument parsing
249 */
250int
251str2u32(char *arg, uint32_t *val)
252{
253        char *err = NULL;
254        uint32_t t;
255
256        errno=0;
257        t = strtoul(arg, &err, 0);
258        if (errno || (err==arg) || ((err != NULL) && *err)) {
259                return -1;
260        }
261
262        *val = t;
263        return 0;
264}
265
266
267int
268str2u16(char *arg, uint16_t *val)
269{
270        char *err = NULL;
271        uint32_t t;
272
273        errno=0;
274        t = strtoul(arg, &err, 0);
275        if (errno || (err==arg) || ((err != NULL) && *err) || (t >= 0x10000)) {
276                return -1;
277        }
278
279        *val = t & 0xFFFF;
280        return 0;
281}
282
283int
284str2u8(char *arg, uint8_t *val)
285{
286        char *err = NULL;
287        uint32_t t;
288
289        errno=0;
290        t = strtoul(arg, &err, 0);
291        if (errno || (err==arg) || ((err != NULL) && *err) || (t >= 0x100)) {
292                return -1;
293        }
294
295        *val = t & 0xFF;
296        return 0;
297}
298
299int
300str2sig(char *arg, uint32_t *sig)
301{
302        if (strlen(arg) != 4)
303                return -1;
304
305        *sig = arg[0] | (arg[1] << 8) | (arg[2] << 16) | (arg[3] << 24);
306
307        return 0;
308}
309
310
311int
312parse_arg(char *arg, char *buf, char *argv[])
313{
314        int res = 0;
315        size_t argl;
316        char *tok;
317        char **ap = &buf;
318        int i;
319
320        memset(argv, 0, MAX_ARG_COUNT * sizeof(void *));
321
322        if ((arg == NULL)) {
323                /* no arguments */
324                return 0;
325        }
326
327        argl = strlen(arg);
328        if (argl == 0) {
329                /* no arguments */
330                return 0;
331        }
332
333        if (argl >= MAX_ARG_LEN) {
334                /* argument is too long */
335                argl = MAX_ARG_LEN-1;
336        }
337
338        memcpy(buf, arg, argl);
339        buf[argl] = '\0';
340
341        for (i = 0; i < MAX_ARG_COUNT; i++) {
342                tok = strsep(ap, ":");
343                if (tok == NULL) {
344                        break;
345                }
346#if 0
347                else if (tok[0] == '\0') {
348                        break;
349                }
350#endif
351                argv[i] = tok;
352                res++;
353        }
354
355        return res;
356}
357
358
359int
360required_arg(char c, char *arg)
361{
362        if (arg == NULL || *arg != '-')
363                return 0;
364
365        ERR("option -%c requires an argument\n", c);
366        return ERR_FATAL;
367}
368
369
370int
371is_empty_arg(char *arg)
372{
373        int ret = 1;
374        if (arg != NULL) {
375                if (*arg) ret = 0;
376        };
377        return ret;
378}
379
380
381void
382csum8_update(uint8_t *p, uint32_t len, struct csum_state *css)
383{
384        for ( ; len > 0; len --) {
385                css->val += *p++;
386        }
387}
388
389
390uint16_t
391csum8_get(struct csum_state *css)
392{
393        uint8_t t;
394
395        t = css->val;
396        return ~t + 1;
397}
398
399
400void
401csum16_update(uint8_t *p, uint32_t len, struct csum_state *css)
402{
403        uint16_t t;
404
405        if (css->odd) {
406                t = css->tmp + (p[0]<<8);
407                css->val += LE16_TO_HOST(t);
408                css->odd = 0;
409                len--;
410                p++;
411        }
412
413        for ( ; len > 1; len -= 2, p +=2 ) {
414                t = p[0] + (p[1] << 8);
415                css->val += LE16_TO_HOST(t);
416        }
417
418        if (len == 1) {
419                css->tmp = p[0];
420                css->odd = 1;
421        }
422}
423
424
425uint16_t
426csum16_get(struct csum_state *css)
427{
428        char pad = 0;
429
430        csum16_update(&pad, 1, css);
431        return ~css->val + 1;
432}
433
434
435void
436csum_init(struct csum_state *css, int size)
437{
438        css->val = 0;
439        css->tmp = 0;
440        css->odd = 0;
441        css->size = size;
442}
443
444
445void
446csum_update(uint8_t *p, uint32_t len, struct csum_state *css)
447{
448        switch (css->size) {
449        case 1:
450                csum8_update(p,len,css);
451                break;
452        case 2:
453                csum16_update(p,len,css);
454                break;
455        }
456}
457
458
459uint16_t
460csum_get(struct csum_state *css)
461{
462        uint16_t ret;
463
464        switch (css->size) {
465        case 1:
466                ret = csum8_get(css);
467                break;
468        case 2:
469                ret = csum16_get(css);
470                break;
471        }
472
473        return ret;
474}
475
476
477/*
478 * routines to write data to the output file
479 */
480int
481write_out_data(FILE *outfile, uint8_t *data, size_t len,
482                struct csum_state *css)
483{
484        errno = 0;
485
486        fwrite(data, len, 1, outfile);
487        if (errno) {
488                ERRS("unable to write output file");
489                return ERR_FATAL;
490        }
491
492        if (css) {
493                csum_update(data, len, css);
494        }
495
496        return 0;
497}
498
499
500int
501write_out_padding(FILE *outfile, size_t len, uint8_t padc,
502                 struct csum_state *css)
503{
504        uint8_t buf[512];
505        size_t buflen = sizeof(buf);
506        int err;
507
508        memset(buf, padc, buflen);
509        while (len > 0) {
510                if (len < buflen)
511                        buflen = len;
512
513                err = write_out_data(outfile, buf, buflen, css);
514                if (err)
515                        return err;
516
517                len -= buflen;
518        }
519
520        return 0;
521}
522
523
524int
525block_stat_file(struct csys_block *block)
526{
527        struct stat st;
528        int err;
529
530        if (block->file_name == NULL)
531                return 0;
532
533        err = stat(block->file_name, &st);
534        if (err){
535                ERRS("stat failed on %s", block->file_name);
536                return ERR_FATAL;
537        }
538
539        block->file_size = st.st_size;
540        return 0;
541}
542
543
544int
545block_writeout_hdr(FILE *outfile, struct csys_block *block)
546{
547        struct csys_header hdr;
548        int res;
549
550        if (block->size_hdr == 0)
551                return 0;
552
553        /* setup header fields */
554        memcpy(hdr.sig, block->sig, 4);
555        hdr.addr = HOST_TO_LE32(block->addr);
556        hdr.size = HOST_TO_LE32(block->size-block->size_hdr);
557
558        DBG(1,"writing header for block");
559        res = write_out_data(outfile, (uint8_t *)&hdr, sizeof(hdr),NULL);
560        return res;
561
562}
563
564
565int
566block_writeout_file(FILE *outfile, struct csys_block *block)
567{
568        char buf[FILE_BUF_LEN];
569        size_t buflen = sizeof(buf);
570        FILE *f;
571        size_t len;
572        int res;
573
574        if (block->file_name == NULL)
575                return 0;
576
577        if (block->file_size == 0)
578                return 0;
579
580        errno = 0;
581        f = fopen(block->file_name,"r");
582        if (errno) {
583                ERRS("unable to open file: %s", block->file_name);
584                return ERR_FATAL;
585        }
586
587        len = block->file_size;
588        while (len > 0) {
589                if (len < buflen)
590                        buflen = len;
591
592                /* read data from source file */
593                errno = 0;
594                fread(buf, buflen, 1, f);
595                if (errno != 0) {
596                        ERRS("unable to read from file: %s", block->file_name);
597                        res = ERR_FATAL;
598                        break;
599                }
600
601                res = write_out_data(outfile, buf, buflen, block->css);
602                if (res)
603                        break;
604
605                len -= buflen;
606        }
607
608        fclose(f);
609        return res;
610}
611
612
613int
614block_writeout_data(FILE *outfile, struct csys_block *block)
615{
616        int res;
617        size_t padlen;
618
619        res = block_writeout_file(outfile, block);
620        if (res)
621                return res;
622
623        /* write padding data if neccesary */
624        padlen = block->size_avail - block->file_size;
625        DBG(1,"padding block, length=%d", padlen);
626        res = write_out_padding(outfile, padlen, block->padc, block->css);
627
628        return res;
629}
630
631
632int
633block_writeout_csum(FILE *outfile, struct csys_block *block)
634{
635        uint16_t csum;
636        int res;
637
638        if (block->size_csum == 0)
639                return 0;
640
641        DBG(1,"writing checksum for block");
642        csum = HOST_TO_LE16(csum_get(block->css));
643        res = write_out_data(outfile, (uint8_t *)&csum, block->size_csum, NULL);
644
645        return res;
646}
647
648
649int
650block_writeout(FILE *outfile, struct csys_block *block)
651{
652        int res;
653        struct csum_state css;
654
655        res = 0;
656
657        if (block == NULL)
658                return res;
659
660        block->css = NULL;
661
662        DBG(2, "writing block, file=%s, file_size=%d, space=%d",
663                block->file_name, block->file_size, block->size_avail);
664        res = block_writeout_hdr(outfile, block);
665        if (res)
666                return res;
667
668        if (block->size_csum != 0) {
669                block->css = &css;
670                csum_init(&css, block->size_csum);
671        }
672
673        res = block_writeout_data(outfile, block);
674        if (res)
675                return res;
676
677        res = block_writeout_csum(outfile, block);
678        if (res)
679                return res;
680
681        return res;
682}
683
684
685int
686write_out_blocks(FILE *outfile)
687{
688        struct csys_block *block;
689        int i, res;
690
691        res = block_writeout(outfile, boot_block);
692        if (res)
693                return res;
694
695        res = block_writeout(outfile, conf_block);
696        if (res)
697                return res;
698
699        res = block_writeout(outfile, webp_block);
700        if (res)
701                return res;
702
703        res = block_writeout(outfile, code_block);
704        if (res)
705                return res;
706
707        res = 0;
708        for (i=0; i < num_blocks; i++) {
709                block = &blocks[i];
710
711                if (block->type != BLOCK_TYPE_XTRA)
712                        continue;
713
714                res = block_writeout(outfile, block);
715                if (res)
716                        break;
717        }
718
719        return res;
720}
721
722
723struct board_info *
724find_board(char *model)
725{
726        struct board_info *ret;
727        struct board_info *board;
728
729        ret = NULL;
730        for (board = boards; board->model != NULL; board++){
731                if (strcasecmp(model, board->model) == 0) {
732                        ret = board;
733                        break;
734                }
735        };
736
737        return ret;
738}
739
740
741int
742parse_opt_board(char ch, char *arg)
743{
744
745        DBG(1,"parsing board option: -%c %s", ch, arg);
746
747        if (board != NULL) {
748                ERR("only one board option allowed");
749                return ERR_FATAL;
750        }
751
752        if (required_arg(ch, arg))
753                return ERR_FATAL;
754
755        board = find_board(arg);
756        if (board == NULL){
757                ERR("invalid/unknown board specified: %s", arg);
758                return ERR_FATAL;
759        }
760
761        return 0;
762}
763
764
765int
766parse_opt_block(char ch, char *arg)
767{
768        char buf[MAX_ARG_LEN];
769        char *argv[MAX_ARG_COUNT];
770        int argc;
771        char *p;
772        struct csys_block *block;
773        int i;
774
775        if ( num_blocks > MAX_NUM_BLOCKS ) {
776                ERR("too many blocks specified");
777                return ERR_FATAL;
778        }
779
780        block = &blocks[num_blocks];
781
782        /* setup default field values */
783        block->need_file = 1;
784        block->padc = 0xFF;
785
786        switch (ch) {
787        case 'b':
788                if (boot_block) {
789                        WARN("only one boot block allowed");
790                        break;
791                }
792                block->type = BLOCK_TYPE_BOOT;
793                boot_block = block;
794                break;
795        case 'c':
796                if (conf_block) {
797                        WARN("only one config block allowed");
798                        break;
799                }
800                block->type = BLOCK_TYPE_CONF;
801                conf_block = block;
802                break;
803        case 'w':
804                if (webp_block) {
805                        WARN("only one web block allowed");
806                        break;
807                }
808                block->type = BLOCK_TYPE_WEBP;
809                block->size_hdr = sizeof(struct csys_header);
810                block->size_csum = 1;
811                block->need_file = 0;
812                webp_block = block;
813                break;
814        case 'r':
815                if (code_block) {
816                        WARN("only one runtime block allowed");
817                        break;
818                }
819                block->type = BLOCK_TYPE_CODE;
820                block->size_hdr = sizeof(struct csys_header);
821                block->size_csum = 2;
822                code_block = block;
823                break;
824        case 'x':
825                block->type = BLOCK_TYPE_XTRA;
826                break;
827        default:
828                ERR("unknown block type \"%c\"", ch);
829                return ERR_FATAL;
830        }
831
832        argc = parse_arg(arg, buf, argv);
833
834        i = 0;
835        p = argv[i++];
836        if (!is_empty_arg(p)) {
837                block->file_name = strdup(p);
838                if (block->file_name == NULL) {
839                        ERR("not enough memory");
840                        return ERR_FATAL;
841                }
842        } else if (block->need_file){
843                ERR("no file specified in %s", arg);
844                return ERR_FATAL;
845        }
846
847        if (block->size_hdr) {
848                p = argv[i++];
849                if (!is_empty_arg(p)) {
850                        if (str2u32(p, &block->addr) != 0) {
851                                ERR("invalid start address in %s", arg);
852                                return ERR_FATAL;
853                        }
854                        block->addr_set = 1;
855                }
856        }
857
858        p = argv[i++];
859        if (!is_empty_arg(p)) {
860                if (str2u32(p, &block->size) != 0) {
861                        ERR("invalid block size in %s", arg);
862                        return ERR_FATAL;
863                }
864                block->size_set = 1;
865        }
866
867        p = argv[i++];
868        if (!is_empty_arg(p) && (str2u8(p, &block->padc) != 0)) {
869                ERR("invalid paddig character in %s", arg);
870                return ERR_FATAL;
871        }
872
873        num_blocks++;
874
875        return 0;
876}
877
878
879int
880process_blocks(void)
881{
882        struct csys_block *block;
883        uint32_t size_avail;
884        int i;
885        int res;
886
887        res = 0;
888        /* collecting stats */
889        for (i = 0; i < num_blocks; i++) {
890                block = &blocks[i];
891                res = block_stat_file(block);
892                if (res)
893                        return res;
894        }
895
896        size_avail = board->flash_size;
897
898        /* bootloader */
899        block = boot_block;
900        if (block) {
901                if (block->size_set) {
902                        board->boot_size= block->size;
903                } else {
904                        block->size = board->boot_size;
905                }
906                if (block->size > size_avail) {
907                        WARN("boot block is too big");
908                        res = ERR_INVALID_IMAGE;
909                }
910        }
911        size_avail -= board->boot_size;
912
913        /* configuration data */
914        block = conf_block;
915        if (block) {
916                if (block->size_set) {
917                        board->conf_size = block->size;
918                } else {
919                        block->size = board->conf_size;
920                }
921                if (block->size > size_avail) {
922                        WARN("config block is too big");
923                        res = ERR_INVALID_IMAGE;
924                }
925
926        }
927        size_avail -= board->conf_size;
928
929        /* webpages */
930        block = webp_block;
931        if (block) {
932                if (block->size_set == 0)
933                        block->size = board->webp_size;
934                board->webp_size = block->size;
935                if (block->size > board->webp_size_max) {
936                        WARN("webpages block is too big");
937                        res = ERR_INVALID_IMAGE;
938                }
939                memcpy(block->sig, board->sig_webp, 4);
940                if (block->addr_set == 0)
941                        block->addr = board->addr_webp;
942        }
943        size_avail -= board->webp_size;
944
945        /* runtime code */
946        block = code_block;
947        if (block) {
948                if (block->size_set == 0) {
949                        block->size =ALIGN(block->file_size+ block->size_hdr +
950                                block->size_csum, 0x10000);
951                }
952                board->code_size = block->size;
953                if (board->code_size > size_avail) {
954                        WARN("code block is too big");
955                        res = ERR_INVALID_IMAGE;
956                }
957                memcpy(code_block->sig, SIG_CSYS, 4);
958                if (code_block->addr_set == 0)
959                        code_block->addr = board->addr_code;
960        }
961        size_avail -= board->code_size;
962
963        for (i = 0; i < num_blocks; i++) {
964                block = &blocks[i];
965
966                if (block->type != BLOCK_TYPE_XTRA)
967                        continue;
968
969                if (block->size_set == 0)
970                        block->size = ALIGN(block->file_size, 0x10000);
971
972                if (block->size > size_avail) {
973                        WARN("file %s is too big, size=%d, avail=%d",
974                                block->file_name, block->file_size,
975                                size_avail);
976                        res = ERR_INVALID_IMAGE;
977                }
978
979                size_avail -= block->size;
980        }
981
982        for (i = 0; i < num_blocks; i++) {
983                block = &blocks[i];
984
985                block->size_avail = block->size - block->size_hdr -
986                        block->size_csum;
987
988                if (block->size_avail < block->file_size) {
989                        WARN("file %s is too big, size=%d, avail=%d",
990                                block->file_name, block->file_size,
991                                block->size_avail);
992                        res = ERR_INVALID_IMAGE;
993                }
994        }
995
996        return res;
997}
998
999
1000int
1001main(int argc, char *argv[])
1002{
1003        int optinvalid = 0;   /* flag for invalid option */
1004        int c;
1005        int res = ERR_FATAL;
1006
1007        FILE *outfile;
1008
1009        progname=basename(argv[0]);
1010
1011        opterr = 0;  /* could not print standard getopt error messages */
1012        while ( 1 ) {
1013                optinvalid = 0;
1014
1015                c = getopt(argc, argv, "b:B:c:dhkr:vw:x:");
1016                if (c == -1)
1017                        break;
1018
1019                switch (c) {
1020                case 'b':
1021                case 'c':
1022                case 'r':
1023                case 'x':
1024                        optinvalid = parse_opt_block(c,optarg);
1025                        break;
1026                case 'w':
1027                        if (optarg != NULL && *optarg == '-') {
1028                                /* rollback */
1029                                optind--;
1030                                optarg = NULL;
1031                        }
1032                        optinvalid = parse_opt_block(c,optarg);
1033                        break;
1034                case 'd':
1035                        invalid_causes_error = 0;
1036                        break;
1037                case 'k':
1038                        keep_invalid_images = 1;
1039                        break;
1040                case 'B':
1041                        optinvalid = parse_opt_board(c,optarg);
1042                        break;
1043                case 'v':
1044                        verblevel++;
1045                        break;
1046                case 'h':
1047                        usage(EXIT_SUCCESS);
1048                        break;
1049                default:
1050                        optinvalid = 1;
1051                        break;
1052                }
1053                if (optinvalid != 0 ){
1054                        ERR("invalid option: -%c", optopt);
1055                        goto out;
1056                }
1057        }
1058
1059        if (board == NULL) {
1060                ERR("no board specified");
1061                goto out;
1062        }
1063
1064        if (optind == argc) {
1065                ERR("no output file specified");
1066                goto out;
1067        }
1068
1069        ofname = argv[optind++];
1070
1071        if (optind < argc) {
1072                ERR("invalid option: %s", argv[optind]);
1073                goto out;
1074        }
1075
1076        res = process_blocks();
1077        if (res == ERR_FATAL)
1078                goto out;
1079
1080        if (res == ERR_INVALID_IMAGE) {
1081                if (invalid_causes_error)
1082                        res = ERR_FATAL;
1083
1084                if (keep_invalid_images == 0) {
1085                        WARN("generation of invalid images disabled", ofname);
1086                        goto out;
1087                }
1088
1089                WARN("generating invalid image", ofname);
1090        }
1091
1092        outfile = fopen(ofname, "w");
1093        if (outfile == NULL) {
1094                ERRS("could not open \"%s\" for writing", ofname);
1095                res = ERR_FATAL;
1096                goto out;
1097        }
1098
1099        if (write_out_blocks(outfile) != 0) {
1100                res = ERR_FATAL;
1101                goto out_flush;
1102        }
1103
1104        DBG(1,"Image file %s completed.", ofname);
1105
1106out_flush:
1107        fflush(outfile);
1108        fclose(outfile);
1109        if (res == ERR_FATAL) {
1110                unlink(ofname);
1111        }
1112out:
1113        if (res == ERR_FATAL)
1114                return EXIT_FAILURE;
1115
1116        return EXIT_SUCCESS;
1117}
Note: See TracBrowser for help on using the repository browser.