OpenWrt – Blame information for rev 3
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | /* |
2 | * Copyright (C) 2011 Vasilis Tsiligiannis <b_tsiligiannis@silverton.gr> |
||
3 | * |
||
4 | * This program is free software; you can redistribute it and/or |
||
5 | * modify it under the terms of the GNU General Public License as |
||
6 | * published by the Free Software Foundation; either version 2 of the |
||
7 | * License, or (at your option) any later version. |
||
8 | * |
||
9 | */ |
||
10 | |||
11 | #include <stdio.h> |
||
12 | #include <stdlib.h> |
||
13 | #include <string.h> |
||
14 | #include <libgen.h> |
||
15 | #include <getopt.h> |
||
16 | #include <errno.h> |
||
17 | #include <sys/stat.h> |
||
18 | #include <endian.h> /* for __BYTE_ORDER */ |
||
19 | |||
20 | #if (__BYTE_ORDER == __LITTLE_ENDIAN) |
||
21 | # define HOST_TO_LE16(x) (x) |
||
22 | # define HOST_TO_LE32(x) (x) |
||
23 | #else |
||
24 | # define HOST_TO_LE16(x) bswap_16(x) |
||
25 | # define HOST_TO_LE32(x) bswap_32(x) |
||
26 | #endif |
||
27 | |||
28 | struct header |
||
29 | { |
||
30 | unsigned char sign[4]; |
||
31 | unsigned int start; |
||
32 | unsigned int flash; |
||
33 | unsigned char model[4]; |
||
34 | unsigned int size; |
||
35 | } __attribute__ ((packed)); |
||
36 | |||
37 | struct finfo |
||
38 | { |
||
39 | char *name; |
||
40 | off_t size; |
||
41 | }; |
||
42 | |||
43 | struct buf |
||
44 | { |
||
45 | char *start; |
||
46 | size_t size; |
||
47 | }; |
||
48 | |||
49 | static char *progname; |
||
50 | |||
51 | static void usage(int status) |
||
52 | { |
||
53 | FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout; |
||
54 | |||
55 | fprintf(stream, "Usage: %s [OPTIONS...]\n", progname); |
||
56 | fprintf(stream, |
||
57 | "\n" |
||
58 | "Options:\n" |
||
59 | " -s <sig> set image signature to <sig>\n" |
||
60 | " -m <model> set model to <model>\n" |
||
61 | " -i <file> read input from file <file>\n" |
||
62 | " -o <file> write output to file <file>\n" |
||
63 | " -f <flash> set flash address to <flash>\n" |
||
3 | office | 64 | " -S <start> set start address to <start>\n"); |
1 | office | 65 | |
66 | exit(status); |
||
67 | } |
||
68 | |||
69 | static int strtou32(char *arg, unsigned int *val) |
||
70 | { |
||
71 | char *endptr = NULL; |
||
72 | |||
73 | errno = 0; |
||
74 | *val = strtoul(arg, &endptr, 0); |
||
75 | if (errno || (endptr == arg) || (*endptr && (endptr != NULL))) { |
||
76 | return EXIT_SUCCESS; |
||
77 | } |
||
78 | |||
79 | return EXIT_FAILURE; |
||
80 | } |
||
81 | |||
82 | static unsigned short fwcsum (struct buf *buf) { |
||
83 | int i; |
||
84 | unsigned short ret = 0; |
||
85 | |||
3 | office | 86 | for (i = 0; i < buf->size / 2; i++) |
87 | ret -= ((unsigned short *) buf->start)[i]; |
||
1 | office | 88 | |
89 | return ret; |
||
90 | } |
||
91 | |||
92 | static int fwread(struct finfo *finfo, struct buf *buf) |
||
93 | { |
||
94 | FILE *f; |
||
95 | |||
96 | f = fopen(finfo->name, "r"); |
||
97 | if (!f) { |
||
98 | fprintf(stderr, "could not open \"%s\" for reading\n", finfo->name); |
||
99 | usage(EXIT_FAILURE); |
||
100 | } |
||
101 | |||
102 | buf->size = fread(buf->start, 1, finfo->size, f); |
||
103 | if (buf->size != finfo->size) { |
||
104 | fprintf(stderr, "unable to read from file \"%s\"\n", finfo->name); |
||
105 | usage(EXIT_FAILURE); |
||
106 | } |
||
107 | |||
108 | fclose(f); |
||
109 | |||
110 | return EXIT_SUCCESS; |
||
111 | } |
||
112 | |||
113 | static int fwwrite(struct finfo *finfo, struct buf *buf) |
||
114 | { |
||
115 | FILE *f; |
||
116 | |||
117 | f = fopen(finfo->name, "w"); |
||
118 | if (!f) { |
||
119 | fprintf(stderr, "could not open \"%s\" for writing\n", finfo->name); |
||
120 | usage(EXIT_FAILURE); |
||
121 | } |
||
122 | |||
123 | buf->size = fwrite(buf->start, 1, finfo->size, f); |
||
124 | if (buf->size != finfo->size) { |
||
125 | fprintf(stderr, "unable to write to file \"%s\"\n", finfo->name); |
||
126 | usage(EXIT_FAILURE); |
||
127 | } |
||
128 | |||
129 | fclose(f); |
||
130 | |||
131 | return EXIT_SUCCESS; |
||
132 | } |
||
133 | |||
134 | int main(int argc, char **argv) |
||
135 | { |
||
136 | struct stat st; |
||
137 | struct header header; |
||
138 | struct buf ibuf, obuf; |
||
139 | struct finfo ifinfo, ofinfo; |
||
140 | unsigned short csum; |
||
141 | int c; |
||
142 | |||
143 | ifinfo.name = ofinfo.name = NULL; |
||
144 | header.flash = header.size = header.start = 0; |
||
145 | progname = basename(argv[0]); |
||
146 | |||
3 | office | 147 | while((c = getopt(argc, argv, "i:o:m:s:f:S:h")) != -1) { |
1 | office | 148 | switch (c) { |
149 | case 'i': |
||
150 | ifinfo.name = optarg; |
||
151 | break; |
||
152 | case 'o': |
||
153 | ofinfo.name = optarg; |
||
154 | break; |
||
155 | case 'm': |
||
156 | if (strlen(optarg) != 4) { |
||
157 | fprintf(stderr, "model must be 4 characters long\n"); |
||
158 | usage(EXIT_FAILURE); |
||
159 | } |
||
160 | memcpy(header.model, optarg, 4); |
||
161 | break; |
||
162 | case 's': |
||
163 | if (strlen(optarg) != 4) { |
||
164 | fprintf(stderr, "signature must be 4 characters long\n"); |
||
165 | usage(EXIT_FAILURE); |
||
166 | } |
||
167 | memcpy(header.sign, optarg, 4); |
||
168 | break; |
||
169 | case 'h': |
||
170 | usage(EXIT_SUCCESS); |
||
171 | break; |
||
172 | case 'f': |
||
173 | if (!strtou32(optarg, &header.flash)) { |
||
174 | fprintf(stderr, "invalid flash address specified\n"); |
||
175 | usage(EXIT_FAILURE); |
||
176 | } |
||
177 | break; |
||
178 | case 'S': |
||
179 | if (!strtou32(optarg, &header.start)) { |
||
180 | fprintf(stderr, "invalid start address specified\n"); |
||
181 | usage(EXIT_FAILURE); |
||
182 | } |
||
183 | break; |
||
184 | default: |
||
185 | usage(EXIT_FAILURE); |
||
186 | break; |
||
187 | } |
||
188 | } |
||
189 | |||
190 | if (ifinfo.name == NULL) { |
||
191 | fprintf(stderr, "no input file specified\n"); |
||
192 | usage(EXIT_FAILURE); |
||
193 | } |
||
194 | |||
195 | if (ofinfo.name == NULL) { |
||
196 | fprintf(stderr, "no output file specified\n"); |
||
197 | usage(EXIT_FAILURE); |
||
198 | } |
||
199 | |||
200 | if (stat(ifinfo.name, &st)) { |
||
201 | fprintf(stderr, "stat failed on %s\n", ifinfo.name); |
||
202 | usage(EXIT_FAILURE); |
||
203 | } |
||
204 | |||
205 | if (header.sign == NULL) { |
||
206 | fprintf(stderr, "no signature specified\n"); |
||
207 | usage(EXIT_FAILURE); |
||
208 | } |
||
209 | |||
210 | if (header.model == NULL) { |
||
211 | fprintf(stderr, "no model specified\n"); |
||
212 | usage(EXIT_FAILURE); |
||
213 | } |
||
214 | |||
215 | if (!header.flash) { |
||
216 | fprintf(stderr, "no flash address specified\n"); |
||
217 | usage(EXIT_FAILURE); |
||
218 | } |
||
219 | |||
220 | if (!header.start) { |
||
221 | fprintf(stderr, "no start address specified\n"); |
||
222 | usage(EXIT_FAILURE); |
||
223 | } |
||
224 | |||
225 | ifinfo.size = st.st_size; |
||
226 | |||
227 | obuf.size = ifinfo.size + sizeof(struct header) + sizeof(unsigned short); |
||
228 | if (obuf.size % sizeof(unsigned short)) |
||
229 | obuf.size++; |
||
230 | |||
231 | obuf.start = malloc(obuf.size); |
||
232 | if (!obuf.start) { |
||
233 | fprintf(stderr, "no memory for buffer\n"); |
||
234 | usage(EXIT_FAILURE); |
||
235 | } |
||
236 | memset(obuf.start, 0, obuf.size); |
||
237 | |||
238 | ibuf.size = ifinfo.size; |
||
239 | ibuf.start = obuf.start + sizeof(struct header); |
||
240 | |||
241 | if (fwread(&ifinfo, &ibuf)) |
||
242 | usage(EXIT_FAILURE); |
||
243 | |||
3 | office | 244 | header.flash = HOST_TO_LE32(header.flash); |
245 | header.size = HOST_TO_LE32(obuf.size - sizeof(struct header)); |
||
246 | header.start = HOST_TO_LE32(header.start); |
||
1 | office | 247 | memcpy (obuf.start, &header, sizeof(struct header)); |
248 | |||
3 | office | 249 | csum = HOST_TO_LE16(fwcsum(&ibuf)); |
1 | office | 250 | memcpy(obuf.start + obuf.size - sizeof(unsigned short), |
251 | &csum, sizeof(unsigned short)); |
||
252 | |||
253 | ofinfo.size = obuf.size; |
||
254 | |||
255 | if (fwwrite(&ofinfo, &obuf)) |
||
256 | usage(EXIT_FAILURE); |
||
257 | |||
258 | return EXIT_SUCCESS; |
||
259 | } |