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