]> git.zerfleddert.de Git - rsbs2/blob - firmware.c
make it possible to change property rights/values in firmware image
[rsbs2] / firmware.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <sys/types.h>
4 #include <sys/stat.h>
5 #include <fcntl.h>
6 #include <unistd.h>
7 #include <errno.h>
8 #include <string.h>
9 #include <strings.h>
10 #include "rsb-crc.h"
11
12 #define FINDSTR(addr, str) (!strncmp((char*)addr, str, strlen(str)))
13
14 struct properties {
15 unsigned int magic;
16 unsigned char unknown0;
17 unsigned char unknown1;
18 unsigned char right_rw;
19 unsigned char rw_mask;
20 unsigned char type1;
21 unsigned char unknown5;
22 unsigned char unknown6;
23 unsigned char unknown7;
24 unsigned char type2;
25 unsigned char val[];
26 };
27
28 #define PROP_ACTION_TRUE (1<<0)
29 #define PROP_ACTION_FALSE (1<<1)
30 #define PROP_ACTION_RO (1<<2)
31 #define PROP_ACTION_RW (1<<3)
32
33 #define PROP_STATUS_NOTFOUND (0)
34 #define PROP_STATUS_WRONGTYPE (1<<0)
35 #define PROP_STATUS_WRONGRIGHTS (1<<1)
36 #define PROP_STATUS_SAMEVAL (1<<2)
37 #define PROP_STATUS_SUCCESS (1<<3)
38
39 struct propaction {
40 char *property;
41 unsigned int action;
42 unsigned int status;
43 struct propaction *next;
44 };
45
46 void show_properties(unsigned char *fw, int len)
47 {
48 int i;
49
50 for (i = 0; i < (len-100 /* XXX */); i++) {
51 if (FINDSTR(fw+i, "/default/fw_prop/") ||
52 FINDSTR(fw+i, "/default/fw_setup/") ||
53 FINDSTR(fw+i, "/default/oem_prop/")) {
54 struct properties *prop;
55 unsigned char *pos = fw + i;
56
57 printf("0x%08x: found setting: %s ", i, pos);
58
59 prop = (struct properties*)(pos + strlen((char*)pos) + 1);
60
61 if (prop->magic != 0x83011111) {
62 printf("ignoring...\n");
63 continue;
64 }
65
66 if (prop->type1 == 0x00 && prop->type2 == 0x04) {
67 printf("STRING: '%s' ", prop->val);
68 } else if (prop->type1 == 0x01 && prop->type2 == 0x01) {
69 printf("BOOL: %s ",(*prop->val ? "TRUE" : "FALSE"));
70 } else if (prop->type1 == 0x04 && prop->type2 == 0x02) {
71 printf("VAL: 0x%x ", *((unsigned int*)prop->val));
72 } else {
73 printf("0x%02x 0x%2x...ignoring\n", prop->type1, prop->type2);
74 continue;
75 }
76
77 if (prop->right_rw == 0x00 && prop->rw_mask == 0x00) {
78 printf("(R-) ");
79 } else if (prop->right_rw == 0x01) {
80 printf("(RW mask: 0x%02x) ", prop->rw_mask);
81 } else {
82 printf("(UNK 0x%02x 0x%02x) ", prop->right_rw, prop->rw_mask);
83 }
84 printf("\n");
85 }
86 }
87 }
88
89 void change_properties(unsigned char *fw, int len, struct propaction *paction)
90 {
91 int i;
92 struct propaction *cpaction;
93
94 for (i = 0; i < (len-100 /* XXX */); i++) {
95 cpaction = paction;
96 while (cpaction != NULL) {
97 if (FINDSTR(fw + i, cpaction->property)) {
98 break;
99 }
100 cpaction = cpaction->next;
101 }
102 if (cpaction != NULL) {
103 struct properties *prop;
104 unsigned char *pos = fw + i;
105
106 prop = (struct properties*)(pos + strlen((char*)pos) + 1);
107
108 if (prop->magic != 0x83011111) {
109 continue;
110 }
111
112 if (cpaction->action & (PROP_ACTION_TRUE|PROP_ACTION_FALSE)) {
113 if (prop->type1 == 0x01 && prop->type2 == 0x01) {
114 if (cpaction->action & PROP_ACTION_TRUE) {
115 if (*prop->val == 0x00) {
116 *prop->val = 0x01;
117 cpaction->status |= PROP_STATUS_SUCCESS;
118 } else {
119 cpaction->status |= PROP_STATUS_SAMEVAL;
120 }
121 } else {
122 if (*prop->val == 0x01) {
123 *prop->val = 0x00;
124 cpaction->status |= PROP_STATUS_SUCCESS;
125 } else {
126 cpaction->status |= PROP_STATUS_SAMEVAL;
127 }
128 }
129 } else {
130 cpaction->status = PROP_STATUS_WRONGTYPE;
131 }
132 }
133 if (cpaction->action & PROP_ACTION_RW) {
134 if (prop->right_rw == 0x00 && prop->rw_mask == 0x00) {
135 prop->right_rw = 0x01;
136 prop->rw_mask = 0x02;
137 cpaction->status |= PROP_STATUS_SUCCESS;
138 } else {
139 cpaction->status |= PROP_STATUS_WRONGRIGHTS;
140 }
141 }
142 if (cpaction->action & PROP_ACTION_RO) {
143 if (prop->right_rw == 0x01 && prop->rw_mask == 0x02) {
144 prop->right_rw = 0x00;
145 prop->rw_mask = 0x00;
146 cpaction->status |= PROP_STATUS_SUCCESS;
147 } else {
148 cpaction->status |= PROP_STATUS_WRONGRIGHTS;
149 }
150 }
151 }
152 }
153 }
154
155 void handle_boarddescription(unsigned char *fw, int len, int patch)
156 {
157 /* 0x01 0x01 0x50 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x88 0x02 0xac 0x01 0xd0 0x05 0x00 0x00 0x6a 0x3a 0x00 0x00 0x06 0x00 0x01 0x00 0x00 0x00 0x00 0x00 */
158 }
159
160 void syntax(char *name)
161 {
162 fprintf(stderr,"Syntax: %s parameters firmware.bin\n", name);
163 fprintf(stderr,"parameters as follows:\n");
164 fprintf(stderr,"\t-d\t\tdisplay all properties of the image\n");
165 fprintf(stderr,"\t-u\t\tupdate checksum of the image\n");
166 fprintf(stderr,"\t-t property\tset 'property' to true\n");
167 fprintf(stderr,"\t-f property\tset 'property' to false\n");
168 fprintf(stderr,"\t-w property\tallow read-write access to 'property'\n");
169 fprintf(stderr,"\t-r property\tallow read-only access to 'property'\n");
170 exit(1);
171 }
172
173 void add_action(int opt, char *optarg, struct propaction **paction) {
174 struct propaction *pos = *paction;
175 struct propaction *prev = NULL;
176
177 while (pos != NULL) {
178 if (!strcmp(pos->property, optarg))
179 break;
180 prev = pos;
181 pos = pos->next;
182 }
183
184 if (pos == NULL) {
185 pos = malloc(sizeof(struct propaction));
186 if (pos == NULL) {
187 perror("malloc");
188 exit(1);
189 }
190 bzero(pos, sizeof(struct propaction));
191 pos->property = optarg;
192
193 if (prev == NULL) {
194 *paction = pos;
195 } else {
196 prev->next = pos;
197 }
198 }
199
200 switch(opt) {
201 case 't':
202 if (pos->action & PROP_ACTION_FALSE) {
203 fprintf(stderr,"inconsistent requests for %s\n",pos->property);
204 exit(1);
205 }
206 pos->action |= PROP_ACTION_TRUE;
207 break;
208 case 'f':
209 if (pos->action & PROP_ACTION_TRUE) {
210 fprintf(stderr,"inconsistent requests for %s\n",pos->property);
211 exit(1);
212 }
213 pos->action |= PROP_ACTION_FALSE;
214 break;
215 case 'w':
216 if (pos->action & PROP_ACTION_RO) {
217 fprintf(stderr,"inconsistent requests for %s\n",pos->property);
218 exit(1);
219 }
220 pos->action |= PROP_ACTION_RW;
221 break;
222 case 'r':
223 if (pos->action & PROP_ACTION_RW) {
224 fprintf(stderr,"inconsistent requests for %s\n",pos->property);
225 exit(1);
226 }
227 pos->action |= PROP_ACTION_RO;
228 break;
229 }
230 }
231
232 int check_crc(unsigned char *fw, int len)
233 {
234 int ret;
235 unsigned int crc, oldcrc;
236
237 ret = rsb_crc2(fw, len, 0x55335053, &crc);
238 oldcrc = (unsigned int)*((unsigned int*)(fw + len - 4));
239
240 printf("Checksum: 0x%08x (%s), should be: 0x%08x\n",
241 crc,
242 (ret ? "NOT OK" : "OK"),
243 oldcrc);
244
245 return ret;
246 }
247
248 int main(int argc, char **argv)
249 {
250 struct stat statbuf;
251 char *file = NULL;
252 unsigned char *fw;
253 int fd;
254 int remaining;
255 int ret;
256 int opt;
257 unsigned int crc;
258 struct propaction *paction = NULL;
259 int showall = 0;
260 int update_crc = 0;
261 int patch_fw = 0;
262
263 if (argc < 2)
264 syntax(argv[0]);
265
266 while ((opt = getopt(argc, argv, "dut:f:w:r:")) != -1) {
267 switch(opt) {
268 case 'd':
269 showall = 1;
270 break;
271 case 'u':
272 update_crc = 1;
273 break;
274 case 't':
275 case 'f':
276 case 'w':
277 case 'r':
278 patch_fw = 1;
279 add_action(opt, optarg, &paction);
280 break;
281 default:
282 syntax(argv[0]);
283 }
284 }
285
286 if (argc > optind) {
287 file = argv[optind];
288 } else {
289 syntax(argv[0]);
290 }
291
292 if (stat(file, &statbuf) == -1) {
293 fprintf(stderr,"%s: ", file);
294 perror("stat");
295 exit(1);
296 }
297
298 if ((fd = open(file, O_RDONLY)) == -1) {
299 fprintf(stderr,"%s: ", file);
300 perror("open");
301 exit(1);
302 }
303
304 if ((fw = malloc(statbuf.st_size)) == NULL) {
305 perror("malloc");
306 exit(1);
307 }
308
309 bzero(fw, statbuf.st_size);
310
311 remaining = statbuf.st_size;
312
313 while(remaining) {
314 if ((ret = read(fd, fw + (statbuf.st_size - remaining), remaining)) == -1) {
315 perror("read");
316 exit(1);
317 }
318 remaining -= ret;
319 }
320 close(fd);
321
322 ret = check_crc(fw, statbuf.st_size);
323 if ((ret != 0) && (!update_crc)) {
324 fprintf(stderr,"Checksum incorrect, aborting...\n");
325 }
326
327 if (patch_fw) {
328 struct propaction *cpaction = paction;
329
330 change_properties(fw, statbuf.st_size, paction);
331
332 printf("\nProperty change results:\n");
333 while(cpaction != NULL) {
334 printf("%s: ", cpaction->property);
335
336 if (cpaction->status == PROP_STATUS_NOTFOUND)
337 printf("NOTFOUND ");
338 if (cpaction->status & PROP_STATUS_SUCCESS)
339 printf("SUCCESS ");
340 if (cpaction->status & PROP_STATUS_SAMEVAL)
341 printf("SAMEVAL ");
342 if (cpaction->status & PROP_STATUS_WRONGTYPE)
343 printf("WRONGTYPE ");
344 if (cpaction->status & PROP_STATUS_WRONGRIGHTS)
345 printf("WRONGRIGHTS ");
346 printf("\n");
347
348 cpaction = cpaction->next;
349 }
350 printf("\n");
351 }
352
353 if (showall)
354 show_properties(fw, statbuf.st_size - 4);
355
356 if (update_crc || patch_fw) {
357 ret = rsb_crc2(fw, statbuf.st_size, 0x55335053, &crc);
358 if (ret == 4) {
359 *((unsigned int*)(fw + statbuf.st_size - 4)) = crc;
360 }
361
362 if (check_crc(fw, statbuf.st_size) == 0) {
363 char *newfile;
364
365 newfile = malloc(strlen(file) + strlen(".patched") + 1);
366 if (newfile == NULL) {
367 perror("malloc");
368 exit(1);
369 }
370 strcpy(newfile, file);
371 strcat(newfile, ".patched");
372
373 printf("Writing %s\n", newfile);
374 if ((fd = open(newfile, O_WRONLY|O_CREAT, 0644)) == -1) {
375 fprintf(stderr,"%s: ", file);
376 perror("open");
377 exit(1);
378 }
379
380 remaining = statbuf.st_size;
381
382 while(remaining) {
383 if ((ret = write(fd, fw + (statbuf.st_size - remaining), remaining)) == -1) {
384 perror("write");
385 exit(1);
386 }
387 remaining -= ret;
388 }
389 close(fd);
390 } else {
391 fprintf(stderr,"Can't set correct checksum, aborting...\n");
392 }
393 }
394
395 exit(0);
396 }
Impressum, Datenschutz