]> git.zerfleddert.de Git - rsbs2/commitdiff
make it possible to change property rights/values in firmware image
authorMichael Gernoth <michael@gernoth.net>
Wed, 28 Jan 2009 22:09:22 +0000 (23:09 +0100)
committerMichael Gernoth <michael@gernoth.net>
Wed, 28 Jan 2009 22:09:22 +0000 (23:09 +0100)
firmware.c
set_better_defaults [new file with mode: 0755]

index a5bdfdb16eb6c795ec27ed8a1d1cd830ab3831fb..6b47e2bf2c32b670107180ee4303377f9b229c9a 100644 (file)
@@ -25,6 +25,24 @@ struct properties {
        unsigned char val[];
 };
 
+#define PROP_ACTION_TRUE       (1<<0)
+#define PROP_ACTION_FALSE      (1<<1)
+#define PROP_ACTION_RO         (1<<2)
+#define PROP_ACTION_RW         (1<<3)
+
+#define PROP_STATUS_NOTFOUND   (0)
+#define PROP_STATUS_WRONGTYPE  (1<<0)
+#define PROP_STATUS_WRONGRIGHTS        (1<<1)
+#define PROP_STATUS_SAMEVAL    (1<<2)
+#define PROP_STATUS_SUCCESS    (1<<3)
+
+struct propaction {
+       char *property;
+       unsigned int action;
+       unsigned int status;
+       struct propaction *next;
+};
+
 void show_properties(unsigned char *fw, int len)
 {
        int i;
@@ -36,7 +54,7 @@ void show_properties(unsigned char *fw, int len)
                        struct properties *prop;
                        unsigned char *pos = fw + i;
 
-                       printf("0x%08x: found setting: %s: ", i, pos);
+                       printf("0x%08x: found setting: %s ", i, pos);
 
                        prop = (struct properties*)(pos + strlen((char*)pos) + 1);
                        
@@ -46,7 +64,7 @@ void show_properties(unsigned char *fw, int len)
                        }
 
                        if (prop->type1 == 0x00 && prop->type2 == 0x04) {
-                               printf("STRING: %s ", prop->val);
+                               printf("STRING: '%s' ", prop->val);
                        } else if (prop->type1 == 0x01 && prop->type2 == 0x01) {
                                printf("BOOL: %s ",(*prop->val ? "TRUE" : "FALSE"));
                        } else if (prop->type1 == 0x04 && prop->type2 == 0x02) {
@@ -68,31 +86,217 @@ void show_properties(unsigned char *fw, int len)
        }
 }
 
+void change_properties(unsigned char *fw, int len, struct propaction *paction)
+{
+       int i;
+       struct propaction *cpaction;
+
+       for (i = 0; i < (len-100 /* XXX */); i++) {
+               cpaction = paction;
+               while (cpaction != NULL) {
+                       if (FINDSTR(fw + i, cpaction->property)) {
+                               break;
+                       }
+                       cpaction = cpaction->next;
+               }
+               if (cpaction != NULL) {
+                       struct properties *prop;
+                       unsigned char *pos = fw + i;
+
+                       prop = (struct properties*)(pos + strlen((char*)pos) + 1);
+
+                       if (prop->magic != 0x83011111) {
+                               continue;
+                       }
+
+                       if (cpaction->action & (PROP_ACTION_TRUE|PROP_ACTION_FALSE)) {
+                               if (prop->type1 == 0x01 && prop->type2 == 0x01) {
+                                       if (cpaction->action & PROP_ACTION_TRUE) {
+                                               if (*prop->val == 0x00) {
+                                                       *prop->val = 0x01;
+                                                       cpaction->status |= PROP_STATUS_SUCCESS;
+                                               } else {
+                                                       cpaction->status |= PROP_STATUS_SAMEVAL;
+                                               }
+                                       } else {
+                                               if (*prop->val == 0x01) {
+                                                       *prop->val = 0x00;
+                                                       cpaction->status |= PROP_STATUS_SUCCESS;
+                                               } else {
+                                                       cpaction->status |= PROP_STATUS_SAMEVAL;
+                                               }
+                                       }
+                               } else {
+                                       cpaction->status = PROP_STATUS_WRONGTYPE;
+                               }
+                       }
+                       if (cpaction->action & PROP_ACTION_RW) {
+                               if (prop->right_rw == 0x00 && prop->rw_mask == 0x00) {
+                                       prop->right_rw = 0x01;
+                                       prop->rw_mask = 0x02;
+                                       cpaction->status |= PROP_STATUS_SUCCESS;
+                               } else {
+                                       cpaction->status |= PROP_STATUS_WRONGRIGHTS;
+                               }
+                       }
+                       if (cpaction->action & PROP_ACTION_RO) {
+                               if (prop->right_rw == 0x01 && prop->rw_mask == 0x02) {
+                                       prop->right_rw = 0x00;
+                                       prop->rw_mask = 0x00;
+                                       cpaction->status |= PROP_STATUS_SUCCESS;
+                               } else {
+                                       cpaction->status |= PROP_STATUS_WRONGRIGHTS;
+                               }
+                       }
+               }
+       }
+}
+
 void handle_boarddescription(unsigned char *fw, int len, int patch)
 {
        /* 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 */
 }
 
+void syntax(char *name)
+{
+       fprintf(stderr,"Syntax: %s parameters firmware.bin\n", name);
+       fprintf(stderr,"parameters as follows:\n");
+       fprintf(stderr,"\t-d\t\tdisplay all properties of the image\n");
+       fprintf(stderr,"\t-u\t\tupdate checksum of the image\n");
+       fprintf(stderr,"\t-t property\tset 'property' to true\n");
+       fprintf(stderr,"\t-f property\tset 'property' to false\n");
+       fprintf(stderr,"\t-w property\tallow read-write access to 'property'\n");
+       fprintf(stderr,"\t-r property\tallow read-only access to 'property'\n");
+       exit(1);
+}
+
+void add_action(int opt, char *optarg, struct propaction **paction) {
+       struct propaction *pos = *paction;
+       struct propaction *prev = NULL;
+       
+       while (pos != NULL) {
+               if (!strcmp(pos->property, optarg))
+                       break;
+               prev = pos;
+               pos = pos->next;
+       }
+
+       if (pos == NULL) {
+               pos = malloc(sizeof(struct propaction));
+               if (pos == NULL) {
+                       perror("malloc");
+                       exit(1);
+               }
+               bzero(pos, sizeof(struct propaction));
+               pos->property = optarg;
+
+               if (prev == NULL) {
+                       *paction = pos;
+               } else {
+                       prev->next = pos;
+               }
+       }
+
+       switch(opt) {
+               case 't':
+                       if (pos->action & PROP_ACTION_FALSE) {
+                               fprintf(stderr,"inconsistent requests for %s\n",pos->property);
+                               exit(1);
+                       }
+                       pos->action |= PROP_ACTION_TRUE;
+                       break;
+               case 'f':
+                       if (pos->action & PROP_ACTION_TRUE) {
+                               fprintf(stderr,"inconsistent requests for %s\n",pos->property);
+                               exit(1);
+                       }
+                       pos->action |= PROP_ACTION_FALSE;
+                       break;
+               case 'w':
+                       if (pos->action & PROP_ACTION_RO) {
+                               fprintf(stderr,"inconsistent requests for %s\n",pos->property);
+                               exit(1);
+                       }
+                       pos->action |= PROP_ACTION_RW;
+                       break;
+               case 'r':
+                       if (pos->action & PROP_ACTION_RW) {
+                               fprintf(stderr,"inconsistent requests for %s\n",pos->property);
+                               exit(1);
+                       }
+                       pos->action |= PROP_ACTION_RO;
+                       break;
+       }
+}
+
+int check_crc(unsigned char *fw, int len)
+{
+       int ret;
+       unsigned int crc, oldcrc;
+
+       ret = rsb_crc2(fw, len, 0x55335053, &crc);
+       oldcrc = (unsigned int)*((unsigned int*)(fw + len - 4));
+
+       printf("Checksum: 0x%08x (%s), should be: 0x%08x\n",
+               crc,
+               (ret ? "NOT OK" : "OK"),
+               oldcrc);
+
+       return ret;
+}
+
 int main(int argc, char **argv)
 {
        struct stat statbuf;
+       char *file = NULL;
        unsigned char *fw;
        int fd;
        int remaining;
        int ret;
-       unsigned int crc, oldcrc;
+       int opt;
+       unsigned int crc;
+       struct propaction *paction = NULL;
+       int showall = 0;
+       int update_crc = 0;
+       int patch_fw = 0;
 
-       if (argc != 2) {
-               fprintf(stderr,"Syntax: %s firmware.bin\n", argv[0]);
-               exit(1);
+       if (argc < 2)
+               syntax(argv[0]);
+
+       while ((opt = getopt(argc, argv, "dut:f:w:r:")) != -1) {
+               switch(opt) {
+                       case 'd':
+                               showall = 1;
+                               break;
+                       case 'u':
+                               update_crc = 1;
+                               break;
+                       case 't':
+                       case 'f':
+                       case 'w':
+                       case 'r':
+                               patch_fw = 1;
+                               add_action(opt, optarg, &paction);
+                               break;
+                       default:
+                               syntax(argv[0]);
+               }
        }
 
-       if (stat(argv[1], &statbuf) == -1) {
+       if (argc > optind) {
+               file = argv[optind];
+       } else {
+               syntax(argv[0]);
+       }
+
+       if (stat(file, &statbuf) == -1) {
+               fprintf(stderr,"%s: ", file);
                perror("stat");
                exit(1);
        }
 
-       if ((fd = open(argv[1], O_RDONLY)) == -1) {
+       if ((fd = open(file, O_RDONLY)) == -1) {
+               fprintf(stderr,"%s: ", file);
                perror("open");
                exit(1);
        }
@@ -113,23 +317,80 @@ int main(int argc, char **argv)
                }
                remaining -= ret;
        }
+       close(fd);
 
-       ret = rsb_crc2(fw, statbuf.st_size, 0x55335053, &crc);
-       oldcrc = (unsigned int)*((unsigned int*)(fw + statbuf.st_size - 4));
+       ret = check_crc(fw, statbuf.st_size);
+       if ((ret != 0) && (!update_crc)) {
+               fprintf(stderr,"Checksum incorrect, aborting...\n");
+       }
 
-       printf("Checksum: 0x%08x (%s), should be: 0x%08x\n",
-               crc,
-               (ret ? "NOT OK" : "OK"),
-               oldcrc);
-       
-       if (1) {
-               show_properties(fw, statbuf.st_size - 4);
-               handle_boarddescription(fw, statbuf.st_size - 4, 0);
-               if (0) {
-                       ret = rsb_crc2(fw, statbuf.st_size, 0x55335053, &crc);
-                       printf("Checksum: 0x%08x\n", crc);
+       if (patch_fw) {
+               struct propaction *cpaction = paction;
+
+               change_properties(fw, statbuf.st_size, paction);
+
+               printf("\nProperty change results:\n");
+               while(cpaction != NULL) {
+                       printf("%s: ", cpaction->property);
+
+                       if (cpaction->status == PROP_STATUS_NOTFOUND)
+                               printf("NOTFOUND ");
+                       if (cpaction->status & PROP_STATUS_SUCCESS)
+                               printf("SUCCESS ");
+                       if (cpaction->status & PROP_STATUS_SAMEVAL)
+                               printf("SAMEVAL ");
+                       if (cpaction->status & PROP_STATUS_WRONGTYPE)
+                               printf("WRONGTYPE ");
+                       if (cpaction->status & PROP_STATUS_WRONGRIGHTS)
+                               printf("WRONGRIGHTS ");
+                       printf("\n");
+                       
+                       cpaction = cpaction->next;
                }
+               printf("\n");
        }
 
+       if (showall)
+               show_properties(fw, statbuf.st_size - 4);
+
+       if (update_crc || patch_fw) {
+               ret = rsb_crc2(fw, statbuf.st_size, 0x55335053, &crc);
+               if (ret == 4) {
+                       *((unsigned int*)(fw + statbuf.st_size - 4)) = crc;
+               }
+
+               if (check_crc(fw, statbuf.st_size) == 0) {
+                       char *newfile;
+
+                       newfile = malloc(strlen(file) + strlen(".patched") + 1);
+                       if (newfile == NULL) {
+                               perror("malloc");
+                               exit(1);
+                       }
+                       strcpy(newfile, file);
+                       strcat(newfile, ".patched");
+
+                       printf("Writing %s\n", newfile);
+                       if ((fd = open(newfile, O_WRONLY|O_CREAT, 0644)) == -1) {
+                               fprintf(stderr,"%s: ", file);
+                               perror("open");
+                               exit(1);
+                       }
+
+                       remaining = statbuf.st_size;
+
+                       while(remaining) {
+                               if ((ret = write(fd, fw + (statbuf.st_size - remaining), remaining)) == -1) {
+                                       perror("write");
+                                       exit(1);
+                               }
+                               remaining -= ret;
+                       }
+                       close(fd);
+               } else {
+                       fprintf(stderr,"Can't set correct checksum, aborting...\n");
+               }
+       }
+       
        exit(0);
 }
diff --git a/set_better_defaults b/set_better_defaults
new file mode 100755 (executable)
index 0000000..7f4250c
--- /dev/null
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+if [ "$1" = "" ]; then
+       echo "Syntax: ${0} firmware.bin"
+       exit 1
+fi
+
+./firmware \
+       -w /default/fw_prop/FP_COMREDIRECT -t /default/fw_prop/FP_COMREDIRECT \
+       -t /default/fw_prop/FP_REMOTE_POWER \
+       -w /default/fw_prop/FP_NO_DIAG_PANEL -f /default/fw_prop/FP_NO_DIAG_PANEL \
+       -w /default/fw_prop/FP_SAC_CONSOLE -t /default/fw_prop/FP_SAC_CONSOLE \
+       "${1}"
+
Impressum, Datenschutz