31b321012d3d1bac13e2ce50eaf6ec2df99f23c0
[openwrt-10.03/.git] / tools / firmware-utils / src / mkdniimg.c
1 /*
2  *  Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org>
3  *
4  *  This program is free software; you can redistribute it and/or modify it
5  *  under the terms of the GNU General Public License version 2 as published
6  *  by the Free Software Foundation.
7  *
8  */
9
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <stdint.h>
13 #include <string.h>
14 #include <unistd.h>     /* for unlink() */
15 #include <libgen.h>
16 #include <getopt.h>     /* for getopt() */
17 #include <stdarg.h>
18 #include <errno.h>
19 #include <sys/stat.h>
20
21 #define DNI_HDR_LEN     128
22
23 /*
24  * Globals
25  */
26 static char *ifname;
27 static char *progname;
28 static char *ofname;
29 static char *version = "1.00.00";
30 static char *region ="NA";
31
32 static char *board_id;
33 /*
34  * Message macros
35  */
36 #define ERR(fmt, ...) do { \
37         fflush(0); \
38         fprintf(stderr, "[%s] *** error: " fmt "\n", \
39                         progname, ## __VA_ARGS__ ); \
40 } while (0)
41
42 #define ERRS(fmt, ...) do { \
43         int save = errno; \
44         fflush(0); \
45         fprintf(stderr, "[%s] *** error: " fmt "\n", \
46                         progname, ## __VA_ARGS__, strerror(save)); \
47 } while (0)
48
49 void usage(int status)
50 {
51         FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout;
52         struct board_info *board;
53
54         fprintf(stream, "Usage: %s [OPTIONS...]\n", progname);
55         fprintf(stream,
56 "\n"
57 "Options:\n"
58 "  -B <board>      create image for the board specified with <board>\n"
59 "  -i <file>       read input from the file <file>\n"
60 "  -o <file>       write output to the file <file>\n"
61 "  -v <version>    set image version to <version>\n"
62 "  -r <region>     set image region to <region>\n"
63 "  -h              show this screen\n"
64         );
65
66         exit(status);
67 }
68
69 int main(int argc, char *argv[])
70 {
71         int res = EXIT_FAILURE;
72         int buflen;
73         int err;
74         struct stat st;
75         char *buf;
76         int i;
77         uint8_t csum;
78
79         FILE *outfile, *infile;
80
81         progname = basename(argv[0]);
82
83         while ( 1 ) {
84                 int c;
85
86                 c = getopt(argc, argv, "B:i:o:v:r:h");
87                 if (c == -1)
88                         break;
89
90                 switch (c) {
91                 case 'B':
92                         board_id = optarg;
93                         break;
94                 case 'i':
95                         ifname = optarg;
96                         break;
97                 case 'o':
98                         ofname = optarg;
99                         break;
100                 case 'v':
101                         version = optarg;
102                         break;
103                 case 'r':
104                         region = optarg;
105                         break;
106                 case 'h':
107                         usage(EXIT_SUCCESS);
108                         break;
109                 default:
110                         usage(EXIT_FAILURE);
111                         break;
112                 }
113         }
114
115         if (board_id == NULL) {
116                 ERR("no board specified");
117                 goto err;
118         }
119
120         if (ifname == NULL) {
121                 ERR("no input file specified");
122                 goto err;
123         }
124
125         if (ofname == NULL) {
126                 ERR("no output file specified");
127                 goto err;
128         }
129
130         err = stat(ifname, &st);
131         if (err){
132                 ERRS("stat failed on %s", ifname);
133                 goto err;
134         }
135
136         buflen = st.st_size + DNI_HDR_LEN + 1;
137         buf = malloc(buflen);
138         if (!buf) {
139                 ERR("no memory for buffer\n");
140                 goto err;
141         }
142
143         memset(buf, 0, DNI_HDR_LEN);
144         snprintf(buf, DNI_HDR_LEN, "device:%s\nversion:V%s\nregion:%s\n",
145                  board_id, version, region);
146
147         infile = fopen(ifname, "r");
148         if (infile == NULL) {
149                 ERRS("could not open \"%s\" for reading", ifname);
150                 goto err_free;
151         }
152
153         errno = 0;
154         fread(buf +  DNI_HDR_LEN, st.st_size, 1, infile);
155         if (errno != 0) {
156                 ERRS("unable to read from file %s", ifname);
157                 goto err_close_in;
158         }
159
160         csum = 0;
161         for (i = 0; i < (st.st_size + DNI_HDR_LEN); i++)
162                 csum += buf[i];
163
164         csum = 0xff - csum;
165         buf[st.st_size + DNI_HDR_LEN] = csum;
166
167         outfile = fopen(ofname, "w");
168         if (outfile == NULL) {
169                 ERRS("could not open \"%s\" for writing", ofname);
170                 goto err_close_in;
171         }
172
173         errno = 0;
174         fwrite(buf, buflen, 1, outfile);
175         if (errno) {
176                 ERRS("unable to write to file %s", ofname);
177                 goto err_close_out;
178         }
179
180         res = EXIT_SUCCESS;
181
182  out_flush:
183         fflush(outfile);
184
185  err_close_out:
186         fclose(outfile);
187         if (res != EXIT_SUCCESS) {
188                 unlink(ofname);
189         }
190
191  err_close_in:
192         fclose(infile);
193
194  err_free:
195         free(buf);
196
197  err:
198         return res;
199 }