7230f09d4921c2b5b75a9a388499a69075a3c40f
[openwrt/openwrt.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 = "";
31 static char *hd_id;
32
33 static char *board_id;
34 /*
35 * Message macros
36 */
37 #define ERR(fmt, ...) do { \
38 fflush(0); \
39 fprintf(stderr, "[%s] *** error: " fmt "\n", \
40 progname, ## __VA_ARGS__ ); \
41 } while (0)
42
43 #define ERRS(fmt, ...) do { \
44 int save = errno; \
45 fflush(0); \
46 fprintf(stderr, "[%s] *** error: " fmt "\n", \
47 progname, ## __VA_ARGS__, strerror(save)); \
48 } while (0)
49
50 void usage(int status)
51 {
52 FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout;
53 struct board_info *board;
54
55 fprintf(stream, "Usage: %s [OPTIONS...]\n", progname);
56 fprintf(stream,
57 "\n"
58 "Options:\n"
59 " -B <board> create image for the board specified with <board>\n"
60 " -i <file> read input from the file <file>\n"
61 " -o <file> write output to the file <file>\n"
62 " -v <version> set image version to <version>\n"
63 " -r <region> set image region to <region>\n"
64 " -H <hd_id> set image hardware id to <hd_id>\n"
65 " -h show this screen\n"
66 );
67
68 exit(status);
69 }
70
71 int main(int argc, char *argv[])
72 {
73 int res = EXIT_FAILURE;
74 int buflen;
75 int err;
76 struct stat st;
77 char *buf;
78 int pos, rem, i;
79 uint8_t csum;
80
81 FILE *outfile, *infile;
82
83 progname = basename(argv[0]);
84
85 while ( 1 ) {
86 int c;
87
88 c = getopt(argc, argv, "B:i:o:v:r:H:h");
89 if (c == -1)
90 break;
91
92 switch (c) {
93 case 'B':
94 board_id = optarg;
95 break;
96 case 'i':
97 ifname = optarg;
98 break;
99 case 'o':
100 ofname = optarg;
101 break;
102 case 'v':
103 version = optarg;
104 break;
105 case 'r':
106 region = optarg;
107 break;
108 case 'H':
109 hd_id = optarg;
110 break;
111 case 'h':
112 usage(EXIT_SUCCESS);
113 break;
114 default:
115 usage(EXIT_FAILURE);
116 break;
117 }
118 }
119
120 if (board_id == NULL) {
121 ERR("no board specified");
122 goto err;
123 }
124
125 if (ifname == NULL) {
126 ERR("no input file specified");
127 goto err;
128 }
129
130 if (ofname == NULL) {
131 ERR("no output file specified");
132 goto err;
133 }
134
135 err = stat(ifname, &st);
136 if (err){
137 ERRS("stat failed on %s", ifname);
138 goto err;
139 }
140
141 buflen = st.st_size + DNI_HDR_LEN + 1;
142 buf = malloc(buflen);
143 if (!buf) {
144 ERR("no memory for buffer\n");
145 goto err;
146 }
147
148 memset(buf, 0, DNI_HDR_LEN);
149 pos = snprintf(buf, DNI_HDR_LEN, "device:%s\nversion:V%s\nregion:%s\n",
150 board_id, version, region);
151 rem = DNI_HDR_LEN - pos;
152 if (pos >= 0 && rem > 1 && hd_id) {
153 snprintf(buf + pos, rem, "hd_id:%s\n", hd_id);
154 }
155
156 infile = fopen(ifname, "r");
157 if (infile == NULL) {
158 ERRS("could not open \"%s\" for reading", ifname);
159 goto err_free;
160 }
161
162 errno = 0;
163 fread(buf + DNI_HDR_LEN, st.st_size, 1, infile);
164 if (errno != 0) {
165 ERRS("unable to read from file %s", ifname);
166 goto err_close_in;
167 }
168
169 csum = 0;
170 for (i = 0; i < (st.st_size + DNI_HDR_LEN); i++)
171 csum += buf[i];
172
173 csum = 0xff - csum;
174 buf[st.st_size + DNI_HDR_LEN] = csum;
175
176 outfile = fopen(ofname, "w");
177 if (outfile == NULL) {
178 ERRS("could not open \"%s\" for writing", ofname);
179 goto err_close_in;
180 }
181
182 errno = 0;
183 fwrite(buf, buflen, 1, outfile);
184 if (errno) {
185 ERRS("unable to write to file %s", ofname);
186 goto err_close_out;
187 }
188
189 res = EXIT_SUCCESS;
190
191 out_flush:
192 fflush(outfile);
193
194 err_close_out:
195 fclose(outfile);
196 if (res != EXIT_SUCCESS) {
197 unlink(ofname);
198 }
199
200 err_close_in:
201 fclose(infile);
202
203 err_free:
204 free(buf);
205
206 err:
207 return res;
208 }