]> git.zerfleddert.de Git - rsbs2/blame - firmware.c
make it possible to change property rights/values in firmware image
[rsbs2] / firmware.c
CommitLineData
972ac24b
MG
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>
7f88d2b6 8#include <string.h>
972ac24b
MG
9#include <strings.h>
10#include "rsb-crc.h"
11
7f88d2b6
MG
12#define FINDSTR(addr, str) (!strncmp((char*)addr, str, strlen(str)))
13
39601b0e
MG
14struct 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
7ac4bfad
MG
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
39struct propaction {
40 char *property;
41 unsigned int action;
42 unsigned int status;
43 struct propaction *next;
44};
45
39601b0e 46void show_properties(unsigned char *fw, int len)
7f88d2b6
MG
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/")) {
39601b0e 54 struct properties *prop;
7f88d2b6 55 unsigned char *pos = fw + i;
7f88d2b6 56
7ac4bfad 57 printf("0x%08x: found setting: %s ", i, pos);
7f88d2b6 58
39601b0e
MG
59 prop = (struct properties*)(pos + strlen((char*)pos) + 1);
60
61 if (prop->magic != 0x83011111) {
7f88d2b6
MG
62 printf("ignoring...\n");
63 continue;
64 }
65
39601b0e 66 if (prop->type1 == 0x00 && prop->type2 == 0x04) {
7ac4bfad 67 printf("STRING: '%s' ", prop->val);
39601b0e
MG
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));
7f88d2b6 72 } else {
39601b0e 73 printf("0x%02x 0x%2x...ignoring\n", prop->type1, prop->type2);
7f88d2b6
MG
74 continue;
75 }
76
39601b0e 77 if (prop->right_rw == 0x00 && prop->rw_mask == 0x00) {
7f88d2b6 78 printf("(R-) ");
39601b0e
MG
79 } else if (prop->right_rw == 0x01) {
80 printf("(RW mask: 0x%02x) ", prop->rw_mask);
7f88d2b6 81 } else {
39601b0e 82 printf("(UNK 0x%02x 0x%02x) ", prop->right_rw, prop->rw_mask);
7f88d2b6
MG
83 }
84 printf("\n");
85 }
86 }
87}
88
7ac4bfad
MG
89void 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
7f88d2b6
MG
155void 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
7ac4bfad
MG
160void 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
173void 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
232int 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
972ac24b
MG
248int main(int argc, char **argv)
249{
250 struct stat statbuf;
7ac4bfad 251 char *file = NULL;
972ac24b
MG
252 unsigned char *fw;
253 int fd;
254 int remaining;
255 int ret;
7ac4bfad
MG
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;
972ac24b 262
7ac4bfad
MG
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 }
972ac24b
MG
284 }
285
7ac4bfad
MG
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);
972ac24b
MG
294 perror("stat");
295 exit(1);
296 }
297
7ac4bfad
MG
298 if ((fd = open(file, O_RDONLY)) == -1) {
299 fprintf(stderr,"%s: ", file);
972ac24b
MG
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 }
7ac4bfad 320 close(fd);
972ac24b 321
7ac4bfad
MG
322 ret = check_crc(fw, statbuf.st_size);
323 if ((ret != 0) && (!update_crc)) {
324 fprintf(stderr,"Checksum incorrect, aborting...\n");
325 }
972ac24b 326
7ac4bfad
MG
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;
7f88d2b6 349 }
7ac4bfad 350 printf("\n");
7f88d2b6 351 }
972ac24b 352
7ac4bfad
MG
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
972ac24b
MG
395 exit(0);
396}
Impressum, Datenschutz