]> git.zerfleddert.de Git - rsbs2/commitdiff
move source files to own subdirectory
authorMichael Gernoth <michael@gernoth.net>
Sat, 6 Mar 2010 10:23:06 +0000 (11:23 +0100)
committerMichael Gernoth <michael@gernoth.net>
Sat, 6 Mar 2010 10:23:06 +0000 (11:23 +0100)
18 files changed:
.gitignore
Makefile
filesystem.c [deleted file]
filesystem.h [deleted file]
firmware.c [deleted file]
rsb-crc.c [deleted file]
rsb-crc.h [deleted file]
rsb-lz.c [deleted file]
rsb-lz.h [deleted file]
src/.gitignore [new file with mode: 0644]
src/Makefile [new file with mode: 0644]
src/filesystem.c [new file with mode: 0644]
src/filesystem.h [new file with mode: 0644]
src/firmware.c [new file with mode: 0644]
src/rsb-crc.c [new file with mode: 0644]
src/rsb-crc.h [new file with mode: 0644]
src/rsb-lz.c [new file with mode: 0644]
src/rsb-lz.h [new file with mode: 0644]

index b861e4c2404e6222a766fd50fe730d81f1816195..1f5a488567442ffebace9064b96c27401c6bd018 100644 (file)
@@ -1,6 +1,2 @@
-filesystem.o
 firmware
-firmware.o
-rsb-crc.o
-rsb-lz.o
 extracted
index 15de0a81175bb62e7a10b817181c0375f9bb3b8a..8517dff17235979a2c41d874c73973cd57d816d2 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,18 +1,13 @@
-CFLAGS=-Wall -O3
+all: firmware
 
-all: firmware 
+firmware: src/firmware
+       ln -s $^ $@
 
-firmware: firmware.o rsb-crc.o rsb-lz.o filesystem.o
-
-firmware.o: firmware.c rsb-crc.h filesystem.h
-
-rsb-crc.o: rsb-crc.c rsb-crc.h
-
-rsb-lz.o: rsb-lz.c rsb-lz.h
-
-filesystem.o: filesystem.c filesystem.h rsb-lz.h
+src/firmware:
+       $(MAKE) -C src firmware
 
 clean:
-       rm -f firmware firmware.o rsb-crc.o rsb-lz.o filesystem.o
+       rm -f firmware
+       $(MAKE) -C src clean
 
 .PHONY: all clean
diff --git a/filesystem.c b/filesystem.c
deleted file mode 100644 (file)
index d644679..0000000
+++ /dev/null
@@ -1,232 +0,0 @@
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <limits.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <strings.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-#include <libgen.h>
-#include "rsb-lz.h"
-#include "filesystem.h"
-
-struct file_entry* get_next_file(unsigned char *fw, int len)
-{
-       static unsigned char *pos;
-       static unsigned char *start;
-       static unsigned char *end;
-       static struct file_entry fent;
-       int name_length;
-
-       if (fw != NULL && len != 0) {
-               pos = fw + 0x28;
-
-#if 0
-               printf("Start of filesystem: 0x%08x\n", *((unsigned int*)pos));
-#endif
-               start = fw;
-               pos = fw + *((unsigned int*)pos);
-               end = fw + len;
-       }
-
-       fent.unknown = *pos;
-       pos++;
-
-       if (fent.unknown == 0x00) {
-               /* EOF */
-               int fill = (4 - ((pos - start) % 4)) % 4;
-               int i;
-
-               for (i = 0; i < fill; i++) {
-                       if (*pos != 0xff) {
-                               fprintf(stderr, "Wrong fill byte after EOF: 0x%02x, aborting!\n", *pos);
-                               exit(1);
-                       }
-                       pos++;
-               }
-
-               if (pos != end) {
-                       fprintf(stderr, "EOF marker not at end-of-file %p <-> %p, aborting!\n", pos, end);
-                       exit(1);
-               }
-
-               return NULL;
-       }
-
-
-       name_length = *((unsigned int*)pos);
-       pos += 4;
-
-       fent.length = *((unsigned int*)pos);
-       pos += 4;
-
-       if ((fent.length > (end - pos)) ||
-           (name_length > (end - pos))) {
-               printf("EOF reached without hitting EOF marker, aborting "
-                       "(unknown: 0x%02x, namelen: 0x%08x, contentlen: 0x%08x!\n",
-                       fent.unknown, name_length, fent.length);
-               exit(1);
-       }
-
-       fent.name = (char*)pos;
-       pos += name_length;
-
-       fent.start = pos;
-       pos += fent.length;
-
-       return &fent;
-}
-
-void extract_files(unsigned char *fw, int len)
-{
-       struct file_entry *fent;
-
-       fent = get_next_file(fw, len);
-       
-       while (fent) {
-               printf("%s: unknown: 0x%02x, length: %d, ",
-                       fent->name, fent->unknown, fent->length);
-
-               if (fent->length > 0) {
-                       write_file(extracted_file(fent->name), fent->start, fent->length);
-                       if (*((unsigned int*)fent->start) == LZ_MAGIC) {
-                               char *lzname;
-                               unsigned char *outbuf;
-                               unsigned int outlen;
-
-                               if ((lzname = strdup(fent->name)) == NULL) {
-                                       perror("strdup");
-                                       exit(1);
-                               }
-
-                               if (!strcmp(lzname + strlen(lzname) - 4 , ".lz")) {
-                                       fprintf(stderr, "Ugh, can't derive filename...\n");
-                                       exit(1);
-                               }
-                               lzname[strlen(lzname) - 3] = 0x00;
-
-                               printf("%s: packed file found, ", lzname);
-
-                               outbuf = extract_lz_file(fent->start, &outlen, 0);
-                               write_file(extracted_file((char*)lzname), outbuf, outlen);
-
-                               free(outbuf);
-                               free(lzname);
-                       } else if (!strcmp(fent->name, "firmware")) {
-                               unsigned char *lzpos;
-                               char lzname[128];
-
-                               bzero(lzname, sizeof(lzname));
-                               strcpy(lzname, "firmware.");
-
-                               lzpos = fent->start + *((unsigned int*)(fent->start + 0x20));
-                               memcpy(lzname + strlen(lzname), lzpos - 4, 4);
-                               lzpos += 4;
-                               if (*((unsigned int*)(lzpos)) == LZ_MAGIC) {
-                                       unsigned char *outbuf;
-                                       unsigned int outlen;
-
-                                       printf("%s: compressed firmware part found", lzname);
-                                       outbuf = extract_lz_file(lzpos, &outlen, 1);
-                                       printf(", ");
-                                       write_file(extracted_file((char*)lzname), outbuf, outlen);
-
-                                       free(outbuf);
-                               }
-                       }
-               } else {
-                       printf(", ignoring...\n");
-               }
-               fent = get_next_file(NULL, 0);
-       }
-}
-
-void replace_add_file(unsigned char *fw, int len, char *fwname, char *lname)
-{
-       fprintf(stderr, "%s: Implement me!\n", __func__);
-       exit(1);
-}
-
-void list_files(unsigned char *fw, int len)
-{
-       struct file_entry *fent;
-
-       for (fent = get_next_file(fw, len); fent != NULL; fent = get_next_file(NULL, 0)) {
-               printf("0x%x %8d %s\n", fent->unknown, fent->length, fent->name);
-       }
-
-}
-
-void mkdir_p(char *dir)
-{
-       char *copy, *parent;
-
-       if ((dir == NULL) || (!strcmp(dir, ".")))
-               return;
-
-       if ((copy = strdup(dir)) == NULL) {
-               perror("strdup");
-               exit(1);
-       }
-       parent = dirname(copy);
-       mkdir_p(parent);
-
-       errno = 0;
-       if (mkdir(dir, 0755) == -1) {
-               if (errno != EEXIST) {
-                       fprintf(stderr, "%s: ", dir);
-                       perror("mkdir");
-                       exit(1);
-               }
-       }
-       free(copy);
-}
-
-void write_file(char *fname, unsigned char *buf, int len)
-{
-       char *filename_c, *dirn;
-       int fd;
-       int remaining;
-       int ret;
-
-       if ((filename_c = strdup(fname)) == NULL) {
-               perror("strdup");
-               exit(1);
-       }
-       dirn = dirname(filename_c);
-       mkdir_p(dirn);
-       free(filename_c);
-
-       if ((fd = open(fname, O_WRONLY|O_CREAT, 0644)) == -1) {
-               fprintf(stderr, "%s: ", fname);
-               perror("open");
-               exit(1);
-       }
-
-       remaining = len;
-
-       while(remaining) {
-               ret = write(fd, buf + (len - remaining), remaining);
-               if (ret < 0) {
-                       perror("write");
-                       exit(1);
-               }
-               remaining -= ret;
-       }
-
-       printf("%s written.\n", fname);
-
-       close(fd);
-}
-
-char *extracted_file(char *fname)
-{
-       static char filename[PATH_MAX];
-
-       strcpy(filename, "extracted/");
-       strcat(filename, fname);
-
-       return filename;
-}
diff --git a/filesystem.h b/filesystem.h
deleted file mode 100644 (file)
index bf9a4c8..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-struct file_entry {
-       char *name;
-       unsigned char *start;
-       int length;
-       unsigned char unknown;
-};
-
-struct file_entry* get_next_file(unsigned char *fw, int len);
-void extract_files(unsigned char *fw, int len);
-void replace_add_file(unsigned char *fw, int len, char *fwname, char *lname);
-void list_files(unsigned char *fw, int len);
-void write_file(char *fname, unsigned char *buf, int len);
-char *extracted_file(char *fname);
diff --git a/firmware.c b/firmware.c
deleted file mode 100644 (file)
index b575012..0000000
+++ /dev/null
@@ -1,530 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include <string.h>
-#include <strings.h>
-#include "rsb-crc.h"
-#include "filesystem.h"
-
-#define FINDSTR(addr, str) (!strncmp((char*)addr, str, strlen(str)))
-
-struct properties {
-       unsigned int magic;
-       unsigned char unknown0;
-       unsigned char unknown1;
-       unsigned char right_rw;
-       unsigned char rw_mask;
-       unsigned char type1;
-       unsigned char unknown5;
-       unsigned char unknown6;
-       unsigned char unknown7;
-       unsigned char type2;
-       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)
-{
-       struct file_entry *fent;
-
-       for (fent = get_next_file(fw, len); fent != NULL; fent = get_next_file(NULL, 0)) {
-               if (FINDSTR(fent->name, "/default/fw_prop/") ||
-                   FINDSTR(fent->name, "/default/fw_setup/") ||
-                   FINDSTR(fent->name, "/default/oem_prop/")) {
-                       struct properties *prop;
-
-                       printf("0x%08x: found setting: %s ", fent->start - fw, fent->name);
-
-                       prop = (struct properties*)fent->start;
-                       
-                       if (prop->magic != 0x83011111) {
-                               printf("ignoring...\n");
-                               continue;
-                       }
-
-                       if (prop->type1 == 0x00 && prop->type2 == 0x04) {
-                               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) {
-                               printf("VAL: 0x%x ", *((unsigned int*)prop->val));
-                       } else {
-                               printf("0x%02x 0x%2x...ignoring\n", prop->type1, prop->type2);
-                               continue;
-                       }
-
-                       if (prop->right_rw == 0x00 && prop->rw_mask == 0x00) {
-                               printf("(R-)");
-                       } else if (prop->right_rw == 0x01) {
-                               printf("(RW mask: 0x%02x)", prop->rw_mask);
-                       } else {
-                               printf("(UNK 0x%02x 0x%02x)", prop->right_rw, prop->rw_mask);
-                       }
-                       printf(", length: %d\n", fent->length);
-               }
-       }
-}
-
-void change_properties(unsigned char *fw, int len, struct propaction *paction)
-{
-       struct file_entry *fent;
-       struct propaction *cpaction;
-
-       for (fent = get_next_file(fw, len); fent != NULL; fent = get_next_file(NULL, 0)) {
-               cpaction = paction;
-               while (cpaction != NULL) {
-                       if (FINDSTR(fent->name, cpaction->property)) {
-                               break;
-                       }
-                       cpaction = cpaction->next;
-               }
-               if (cpaction != NULL) {
-                       struct properties *prop;
-
-                       prop = (struct properties*)fent->start;
-
-                       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;
-                               }
-                       }
-               }
-       }
-}
-
-#define BD_SERIAL1     0x14,0x02
-#define BD_ICMB                0x14,0x04
-#define BD_LAN         0x14,0x08
-#define BD_SERIAL2     0x14,0x10
-#define BD_SERIAL3     0x14,0x20
-#define BD_USB         0x14,0x40
-#define BD_PCI         0x15,0x03
-#define BD_LPC         0x15,0x04
-#define BD_VGA         0x15,0x08
-#define BD_BATTERY     0x15,0x10
-#define BD_ACDC                0x15,0x20
-#define BD_STANDBY     0x15,0x40
-#define BD_POWERCONN   0x15,0x70
-#define BD_DVI         0x15,0x80
-#define BD_PWRATX      0x16,0x01
-#define BD_PWRRELAY    0x16,0x02
-#define BD_PS2A                0x19,0xff
-
-#define MAGIC(fn, args...) fn(args)
-
-#define _BD_IS_SET(bd, byte, bits) (bd[byte] & bits)
-#define BD_IS_SET(bd, ident) MAGIC(_BD_IS_SET, bd, BD_##ident)
-#define BD_TEXT(bd, ident) (BD_IS_SET(bd, ident) ? "TRUE" : "FALSE")
-
-#define _BD_SET(bd, byte, bits) (bd[byte] |= bits)
-#define BD_SET(bd, ident) MAGIC(_BD_SET, bd, BD_##ident)
-
-void print_boarddescription(unsigned char *bd)
-{
-       int j;
-
-       for (j = 0; j < 32; j++) {
-               printf("%02x ", *(bd+j));
-       }
-       printf("\n");
-
-       /* com/agilent/rmc/amr/AmrMaster.class
-        * com/agilent/rmc/mgui/RmcPanel.class
-        * com/agilent/rmc/mgui/panels/AvrManualConfig.class
-        * com/agilent/rmc/mgui/panels/CardConf.jad
-        * com/agilent/rmc/mgui/panels/PowerMgmtConf.jad
-        * com/agilent/rmc/mgui/panels/RemoteDiskConf.jad
-        */
-       printf("\tserial1Present\t\t: %s\n", BD_TEXT(bd, SERIAL1));
-       printf("\ticmbPresent\t\t: %s\n", BD_TEXT(bd, ICMB));
-       printf("\tlanPresent\t\t: %s\n", BD_TEXT(bd, LAN));
-       printf("\tserial2Present\t\t: %s\n", BD_TEXT(bd, SERIAL2));
-       printf("\tserial3Present\t\t: %s\n", BD_TEXT(bd, SERIAL3));
-       printf("\tusbPresent\t\t: %s\n", BD_TEXT(bd, USB));
-       printf("\tpciPresent\t\t: %s\n", BD_TEXT(bd, PCI));
-       printf("\tlpcPresent\t\t: %s\n", BD_TEXT(bd, LPC));
-       printf("\tvgaPresent\t\t: %s\n", BD_TEXT(bd, VGA));
-       printf("\tbatteryPresent\t\t: %s\n", BD_TEXT(bd, BATTERY));
-       printf("\tacdcPresent\t\t: %s\n", BD_TEXT(bd, ACDC));
-       printf("\tstandbyPresent\t\t: %s\n", BD_TEXT(bd, STANDBY));
-       printf("\thasPowerConnectors\t: %s\n", BD_TEXT(bd, POWERCONN));
-       printf("\tdviPresent\t\t: %s\n", BD_TEXT(bd, DVI));
-       printf("\tpowerSwitchATX\t\t: %s\n", BD_TEXT(bd, PWRATX));
-       printf("\tpowerSwitchRelay\t: %s\n", BD_TEXT(bd, PWRRELAY));
-       /* 22 & 4 */
-       printf("\tps2aPresent\t\t: %s\n", BD_TEXT(bd, PS2A));
-}
-
-void handle_boarddescription(unsigned char *fw, int len, int patch)
-{
-       struct file_entry *fent;
-       unsigned char *pos;
-       
-       for (fent = get_next_file(fw, len); fent != NULL; fent = get_next_file(NULL, 0)) {
-               if (!strcmp(fent->name, "pdata"))
-                       break;
-       }
-
-       if (fent == NULL) {
-               fprintf(stderr, "pdata file not found, aborting!\n");
-               exit(1);
-       }
-
-
-       pos = fent->start;
-       /* MAGIC? */
-       if (*((unsigned int*)pos) != 0x00002802) {
-               fprintf(stderr, "pdata magic does not match, aborting!\n");
-               exit(1);
-       }
-
-       pos += 26;
-
-       /* MAGIC2? */
-       if (*((unsigned int*)pos) != 0x00500101) {
-               fprintf(stderr, "pdata magic2 does not match, aborting!\n");
-               exit(1);
-       }
-
-       if (patch) {
-               /* Enable ATX and relay power switching */
-               BD_SET(pos, PWRATX);
-               BD_SET(pos, PWRRELAY);
-       }
-
-       printf("0x%08x: BOARD_DESCRIPTION: ", fent->start - fw);
-       print_boarddescription(pos);
-}
-
-void syntax(char *name)
-{
-       fprintf(stderr,"Syntax: %s parameters firmware.bin\n", name);
-       fprintf(stderr,"parameters as follows:\n");
-       fprintf(stderr,"\t-d\t\t\tdisplay all properties of the image\n");
-       fprintf(stderr,"\t-u\t\t\tupdate checksum of the image\n");
-       fprintf(stderr,"\t-b\t\t\tmodify BOARD_DESCRIPTION for more power-switch options\n");
-       fprintf(stderr,"\t-e\t\t\textract files in firmware\n");
-       fprintf(stderr,"\t-l\t\t\tlist files in firmware\n");
-       fprintf(stderr,"\t-t property\t\tset 'property' to true\n");
-       fprintf(stderr,"\t-f property\t\tset 'property' to false\n");
-       fprintf(stderr,"\t-w property\t\tallow read-write access to 'property'\n");
-       fprintf(stderr,"\t-r property\t\tallow read-only access to 'property'\n");
-       fprintf(stderr,"\t-x fw_file=local_file\treplace or add fw_file with content of local_file\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;
-}
-
-void check_image(unsigned char *fw, int len)
-{
-       struct file_entry *fent;
-       char *last_name = NULL;
-
-       /* get_next_file will abort on error */
-       fent = get_next_file(fw, len);
-       while (fent != NULL) {
-               last_name = fent->name;
-               fent = get_next_file(NULL, 0);
-       }
-}
-
-int main(int argc, char **argv)
-{
-       struct stat statbuf;
-       char *file = NULL;
-       unsigned char *fw;
-       int fd;
-       int remaining;
-       int ret;
-       int opt;
-       unsigned int crc;
-       struct propaction *paction = NULL;
-       int showall = 0;
-       int update_crc = 0;
-       int patch_bd = 0;
-       int patch_fw = 0;
-       int extract = 0;
-       int list = 0;
-
-       if (argc < 2)
-               syntax(argv[0]);
-
-       while ((opt = getopt(argc, argv, "dubelt:f:w:r:x:")) != -1) {
-               switch(opt) {
-                       case 'd':
-                               showall = 1;
-                               break;
-                       case 'u':
-                               update_crc = 1;
-                               break;
-                       case 'b':
-                               patch_bd = 1;
-                               break;
-                       case 'e':
-                               extract = 1;
-                               break;
-                       case 'l':
-                               list = 1;
-                               break;
-                       case 't':
-                       case 'f':
-                       case 'w':
-                       case 'r':
-                               patch_fw = 1;
-                               add_action(opt, optarg, &paction);
-                               break;
-                       case 'x':
-                               replace_add_file(NULL, 0, NULL, NULL);
-                               break;
-                       default:
-                               syntax(argv[0]);
-               }
-       }
-
-       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(file, O_RDONLY)) == -1) {
-               fprintf(stderr,"%s: ", file);
-               perror("open");
-               exit(1);
-       }
-
-       if ((fw = malloc(statbuf.st_size)) == NULL) {
-               perror("malloc");
-               exit(1);
-       }
-
-       bzero(fw, statbuf.st_size);
-
-       remaining = statbuf.st_size;
-
-       while(remaining) {
-               if ((ret = read(fd, fw + (statbuf.st_size - remaining), remaining)) == -1) {
-                       perror("read");
-                       exit(1);
-               }
-               remaining -= ret;
-       }
-       close(fd);
-
-       ret = check_crc(fw, statbuf.st_size);
-       if ((ret != 0) && (!update_crc)) {
-               fprintf(stderr,"Checksum incorrect, aborting...\n");
-               exit(1);
-       }
-
-       check_image(fw, statbuf.st_size - 4);
-
-       if (patch_fw) {
-               struct propaction *cpaction = paction;
-
-               change_properties(fw, statbuf.st_size - 4, 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 (patch_bd) {
-               handle_boarddescription(fw, statbuf.st_size - 4, 1);
-       }
-
-       if (showall) {
-               show_properties(fw, statbuf.st_size - 4);
-               handle_boarddescription(fw, statbuf.st_size - 4, 0);
-       }
-
-       if (list) {
-               list_files(fw, statbuf.st_size - 4);
-       }
-
-       if (extract) {
-               extract_files(fw, statbuf.st_size - 4);
-       }
-
-       if (update_crc || patch_fw || patch_bd) {
-               ret = rsb_crc2(fw, statbuf.st_size, 0x55335053, &crc);
-               if (ret == 4) {
-                       *((unsigned int*)(fw + statbuf.st_size - 4)) = crc;
-               }
-
-               check_image(fw, statbuf.st_size-4);
-
-               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("Firmware ");
-                       write_file(newfile, fw, statbuf.st_size);
-               } else {
-                       fprintf(stderr,"Can't set correct checksum, aborting...\n");
-               }
-       }
-       
-       exit(0);
-}
diff --git a/rsb-crc.c b/rsb-crc.c
deleted file mode 100644 (file)
index 6a2bf99..0000000
--- a/rsb-crc.c
+++ /dev/null
@@ -1,54 +0,0 @@
-#include <stdio.h>
-
-#define POLY 0x04c11db7
-
-unsigned int rsb_crc(unsigned int r11_crc, unsigned char *r10_buf, unsigned int r14_len) {
-       unsigned int r6_pos = 0;
-       unsigned int r3_data;
-       int r5_bit;
-
-       while (r6_pos < r14_len) {
-               r3_data = (*(r6_pos+r10_buf)) << 24;
-               r11_crc = r11_crc ^ r3_data;
-
-               r5_bit = 8;
-               
-               do {
-                       r3_data = r11_crc & 0x80000000;
-
-                       if (r3_data != 0) {
-                               r3_data = r11_crc << 1;
-                               r11_crc = r3_data ^ POLY;
-                       } else {
-                               r11_crc = r11_crc << 1;
-                       }
-                       r5_bit--;
-               } while (r5_bit);
-
-               r6_pos++;
-       }
-
-       return r11_crc;
-}
-
-unsigned int rsb_crc2(unsigned char *r0_buf, unsigned int r1_buflen, unsigned int r2_magic, unsigned int *crc_out) {
-       unsigned int r4_len;
-       unsigned int file_crc;
-
-       r4_len = *(unsigned int*)(r0_buf + 0x20);
-
-       if (*((unsigned int*)(r0_buf + 0x24)) != r2_magic)
-               return 2; /* MAGIC does not match */
-       
-       if (r1_buflen < r4_len)
-               return 3; /* image to small */
-       
-       *crc_out = ~rsb_crc(~0x0, r0_buf, r4_len);
-
-       file_crc = *((unsigned int*)(r0_buf + r4_len));
-
-       if (file_crc != *crc_out)
-               return 4;
-
-       return 0;
-}
diff --git a/rsb-crc.h b/rsb-crc.h
deleted file mode 100644 (file)
index f97e6da..0000000
--- a/rsb-crc.h
+++ /dev/null
@@ -1,2 +0,0 @@
-unsigned int rsb_crc(unsigned int r11_crc, unsigned char *r10_buf, unsigned int r14_len);
-unsigned int rsb_crc2(unsigned char *r0_buf, unsigned int r1_buflen, unsigned int r2_magic, unsigned int *crc_out);
diff --git a/rsb-lz.c b/rsb-lz.c
deleted file mode 100644 (file)
index bb735d6..0000000
--- a/rsb-lz.c
+++ /dev/null
@@ -1,316 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <strings.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-#include "rsb-crc.h"
-#include "rsb-lz.h"
-#include "filesystem.h"
-
-void err_exit(const char *fname)
-{
-       fprintf(stderr,"%s: error extracting...\n", fname);
-       exit(1);
-}
-
-struct data_in_s {
-       unsigned char *start;
-       unsigned char *stop;
-       unsigned char bitpos;
-       unsigned char byte;
-};
-
-struct data_out_s {
-       unsigned char *pos;
-       unsigned char *end;
-};
-
-unsigned char get_next_in_byte(struct data_in_s *data_in)
-{
-       unsigned char byte;
-
-       if (data_in->stop < data_in->start)
-               err_exit(__func__);
-
-       byte = *(data_in->start);
-       data_in->start++;
-
-       return byte;
-}
-
-unsigned char get_next_bit(struct data_in_s *data_in)
-{
-       unsigned char bitval;
-
-       if (data_in->bitpos == 0x80) {
-               data_in->byte = get_next_in_byte(data_in);
-       }
-
-       bitval = data_in->bitpos & data_in->byte;
-
-       data_in->bitpos >>= 1;
-       if (data_in->bitpos == 0) {
-               data_in->bitpos = 0x80;
-       }
-
-       if (bitval == 0)
-               return 0;
-
-       return 1;
-}
-
-unsigned int get_next_bits(struct data_in_s *data_in, unsigned int bits)
-{
-       unsigned int bit;
-       unsigned int next_bits;
-
-       bit = 1 << (bits - 1);
-
-       next_bits = 0;
-       while (bit != 0) {
-               if (data_in->bitpos == 0x80) {
-                       data_in->byte = get_next_in_byte(data_in);
-               }
-
-               if ((data_in->bitpos & data_in->byte) != 0)
-                       next_bits = next_bits | bit;
-
-               bit = bit >> 1;
-
-               data_in->bitpos >>= 1;
-
-               if(data_in->bitpos == 0) {
-                       data_in->bitpos = 0x80;
-               }
-       }
-
-       return next_bits;
-}
-
-void write_byte(unsigned char byte, struct data_out_s *data_out)
-{
-       if (data_out->pos > data_out->end) {
-               err_exit(__func__);
-       }
-
-       *(data_out->pos) = byte;
-       data_out->pos++;
-}
-
-void lz_expand(struct data_in_s *data_in, struct data_out_s *data_out)
-{
-       unsigned int pos;
-       unsigned int wordoffset;
-       unsigned int i;
-       unsigned char byte;
-       unsigned int wordlen;
-       unsigned char buf[1024];
-
-       pos = 1;
-
-       while (1) {
-               while (1) {
-                       /* Compressed/uncompressed? */
-                       if (get_next_bit(data_in) == 0)
-                               break;
-
-                       /* Uncompressed byte */
-                       byte = get_next_bits(data_in, 8);
-
-                       write_byte(byte, data_out);
-
-                       /* Save byte in buffer, to be reused later */
-                       buf[pos] = byte;
-                       pos = (pos + 1) & 0x3ff;
-               }
-
-               /* offset for start of dictionary word */
-               wordoffset = get_next_bits(data_in, 0x0a);
-               if(wordoffset == 0)
-                       return;
-
-               /* length of dictionary word used */
-               wordlen = get_next_bits(data_in, 0x04) + 1;
-               for (i = 0; i <= wordlen ; i++) {
-                       /* lookup dictionary byte */
-                       byte = buf[(wordoffset + i) & 0x3ff];
-                       write_byte(byte, data_out);
-                       /* Save byte in buffer, to be reused later */
-                       buf[pos] = byte;
-                       pos = (pos + 1) & 0x3ff;
-               }
-       }
-}
-
-void set_next_bit(unsigned char *buf, unsigned int set, unsigned int *currbit) {
-       unsigned char *pos;
-       unsigned char bitpos;
-
-       if (set) {
-               pos = buf + ((*currbit) / 8);
-               bitpos = 0x80 >> ((*currbit) % 8);
-               *pos |= bitpos;
-       }
-
-       *currbit = *currbit + 1;
-}
-
-void write_bits(unsigned char *buf, unsigned int data, unsigned int bits, unsigned int *currbit) {
-       int i;
-       unsigned int bitpos;
-
-       bitpos = 1 << (bits - 1);
-
-       for (i = 0; i < bits; i++) {
-               set_next_bit(buf, data & bitpos, currbit);
-               bitpos >>= 1;
-       }
-}
-
-unsigned char *compress_lz(unsigned char *inbuf, int inlen, int *outlen)
-{
-       unsigned char *end = inbuf + inlen;
-       unsigned char *outbuf;
-       unsigned char window[1024];
-       int pos = 0;
-       int fill = 0;
-       unsigned int currbit = 0;
-       int offset;
-       int wordlen;
-       int found;
-       int i;
-
-       if ((outbuf = malloc((inlen * 2) + 4)) == NULL) {
-               perror("malloc");
-       }
-
-       *((unsigned int*)outbuf) = LZ_MAGIC;
-       currbit = 8 * 8;
-
-       while(inbuf < end) {
-               found = 0;
-               for (wordlen = 17; wordlen > 1; wordlen--) {
-                       for (offset = 1; offset < ((fill < 1023) ? fill : 1023); offset++) {
-                               if ((fill < 1023) &&
-                                   (wordlen + offset > fill))
-                                       break;
-
-                               for (i = 0; i < wordlen; i++) {
-                                       if (inbuf[i] != window[(offset + i) & 0x3ff]) {
-                                               break;
-                                       }
-                               }
-                               if (i == wordlen)
-                                       found = 1;
-                       }
-                       if (found)
-                               break;
-               }
-
-               if (found) {
-                       write_bits(outbuf, 0x00, 0x01, &currbit);
-                       write_bits(outbuf, offset, 0x0a, &currbit);
-                       write_bits(outbuf, wordlen - 1, 0x04, &currbit);
-                       for (i = 0; i < wordlen; i++) {
-                               window[pos] = *(inbuf + i);
-                               pos = (pos + 1) & 0x3ff;
-                       }
-                       inbuf += wordlen;
-
-                       if (fill < sizeof(window))
-                               fill += wordlen;
-               } else {
-                       write_bits(outbuf, 0x01, 0x01, &currbit);
-                       write_bits(outbuf, *inbuf, 0x08, &currbit);
-                       window[pos] = *inbuf;
-                       pos = (pos + 1) & 0x3ff;
-                       inbuf++;
-                       if (fill < sizeof(window))
-                               fill++;
-               }
-       }
-
-       write_bits(outbuf, 0x00, 0x01, &currbit);
-       write_bits(outbuf, 0x00, 0x0a, &currbit);
-
-       *outlen = (currbit / 8) + 1;
-
-       *((unsigned int*)(outbuf + 4)) = *outlen;
-
-       return outbuf;
-}
-
-/* Checksum is only used for the compressed firmware in 'firmware' */
-unsigned int crc_check(unsigned char *buf, unsigned int len, unsigned int magic)
-{
-       unsigned int file_crc;
-       unsigned int my_len;
-       unsigned int crc;
-       unsigned int my_magic;
-
-       my_len = *((unsigned int*)(buf + 0x20));
-       my_magic = *((unsigned int*)(buf + 0x24));
-
-       if (my_magic != magic) {
-               printf("\nmagic: 0x%08x <-> 0x%08x\n", my_magic, magic);
-               return 2;
-       }
-       
-       if (len < my_len)
-               return 3;
-
-       crc = ~rsb_crc(~0x00, buf, len);
-       file_crc = *((unsigned int*)(buf + len));
-
-       if (file_crc != crc) {
-               printf("\nChecksums: 0x%08x <-> 0x%08x!\n", crc, file_crc);
-               return 4;
-       }
-
-       return 0;
-}
-
-unsigned char *extract_lz_file(unsigned char *inbuf, unsigned int *outlen , unsigned char check_crc)
-{
-       unsigned char *outbuf;
-       struct data_in_s data_in;
-       struct data_out_s data_out;
-
-       if (*((unsigned int*)inbuf) != LZ_MAGIC)
-               err_exit(__func__);
-
-       *outlen = *((unsigned int*)(inbuf + 4));
-       printf(", length: %d", *outlen);
-
-       if ((outbuf = malloc(*outlen)) == NULL) {
-               perror("malloc");
-               exit(1);
-       }
-
-       bzero(outbuf, *outlen);
-
-       data_in.start = inbuf + 8;
-       data_in.stop = inbuf + *outlen;
-       data_in.byte = 0x00;
-       data_in.bitpos = 0x80;
-
-       data_out.pos = outbuf;
-       data_out.end = outbuf + *outlen;
-
-       lz_expand(&data_in, &data_out);
-
-       if (check_crc) {
-               unsigned int crclen;
-               int ret;
-
-               crclen = *((unsigned int*)(outbuf + 0x20));
-
-               if ((ret = crc_check(outbuf, crclen, 0x46335053)) != 0) {
-                       printf("crc_check return: %d\n", ret);
-                       err_exit(__func__);
-               }
-       }
-
-       return outbuf;
-}
diff --git a/rsb-lz.h b/rsb-lz.h
deleted file mode 100644 (file)
index 4cf2c82..0000000
--- a/rsb-lz.h
+++ /dev/null
@@ -1,4 +0,0 @@
-#define LZ_MAGIC 0x6110beef
-
-unsigned char *extract_lz_file(unsigned char *inbuf, unsigned int *outlen , unsigned char check_crc);
-unsigned char *compress_lz(unsigned char *inbuf, int inlen, int *outlen);
diff --git a/src/.gitignore b/src/.gitignore
new file mode 100644 (file)
index 0000000..8112a8e
--- /dev/null
@@ -0,0 +1,5 @@
+filesystem.o
+firmware
+firmware.o
+rsb-crc.o
+rsb-lz.o
diff --git a/src/Makefile b/src/Makefile
new file mode 100644 (file)
index 0000000..15de0a8
--- /dev/null
@@ -0,0 +1,18 @@
+CFLAGS=-Wall -O3
+
+all: firmware 
+
+firmware: firmware.o rsb-crc.o rsb-lz.o filesystem.o
+
+firmware.o: firmware.c rsb-crc.h filesystem.h
+
+rsb-crc.o: rsb-crc.c rsb-crc.h
+
+rsb-lz.o: rsb-lz.c rsb-lz.h
+
+filesystem.o: filesystem.c filesystem.h rsb-lz.h
+
+clean:
+       rm -f firmware firmware.o rsb-crc.o rsb-lz.o filesystem.o
+
+.PHONY: all clean
diff --git a/src/filesystem.c b/src/filesystem.c
new file mode 100644 (file)
index 0000000..d644679
--- /dev/null
@@ -0,0 +1,232 @@
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <limits.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <libgen.h>
+#include "rsb-lz.h"
+#include "filesystem.h"
+
+struct file_entry* get_next_file(unsigned char *fw, int len)
+{
+       static unsigned char *pos;
+       static unsigned char *start;
+       static unsigned char *end;
+       static struct file_entry fent;
+       int name_length;
+
+       if (fw != NULL && len != 0) {
+               pos = fw + 0x28;
+
+#if 0
+               printf("Start of filesystem: 0x%08x\n", *((unsigned int*)pos));
+#endif
+               start = fw;
+               pos = fw + *((unsigned int*)pos);
+               end = fw + len;
+       }
+
+       fent.unknown = *pos;
+       pos++;
+
+       if (fent.unknown == 0x00) {
+               /* EOF */
+               int fill = (4 - ((pos - start) % 4)) % 4;
+               int i;
+
+               for (i = 0; i < fill; i++) {
+                       if (*pos != 0xff) {
+                               fprintf(stderr, "Wrong fill byte after EOF: 0x%02x, aborting!\n", *pos);
+                               exit(1);
+                       }
+                       pos++;
+               }
+
+               if (pos != end) {
+                       fprintf(stderr, "EOF marker not at end-of-file %p <-> %p, aborting!\n", pos, end);
+                       exit(1);
+               }
+
+               return NULL;
+       }
+
+
+       name_length = *((unsigned int*)pos);
+       pos += 4;
+
+       fent.length = *((unsigned int*)pos);
+       pos += 4;
+
+       if ((fent.length > (end - pos)) ||
+           (name_length > (end - pos))) {
+               printf("EOF reached without hitting EOF marker, aborting "
+                       "(unknown: 0x%02x, namelen: 0x%08x, contentlen: 0x%08x!\n",
+                       fent.unknown, name_length, fent.length);
+               exit(1);
+       }
+
+       fent.name = (char*)pos;
+       pos += name_length;
+
+       fent.start = pos;
+       pos += fent.length;
+
+       return &fent;
+}
+
+void extract_files(unsigned char *fw, int len)
+{
+       struct file_entry *fent;
+
+       fent = get_next_file(fw, len);
+       
+       while (fent) {
+               printf("%s: unknown: 0x%02x, length: %d, ",
+                       fent->name, fent->unknown, fent->length);
+
+               if (fent->length > 0) {
+                       write_file(extracted_file(fent->name), fent->start, fent->length);
+                       if (*((unsigned int*)fent->start) == LZ_MAGIC) {
+                               char *lzname;
+                               unsigned char *outbuf;
+                               unsigned int outlen;
+
+                               if ((lzname = strdup(fent->name)) == NULL) {
+                                       perror("strdup");
+                                       exit(1);
+                               }
+
+                               if (!strcmp(lzname + strlen(lzname) - 4 , ".lz")) {
+                                       fprintf(stderr, "Ugh, can't derive filename...\n");
+                                       exit(1);
+                               }
+                               lzname[strlen(lzname) - 3] = 0x00;
+
+                               printf("%s: packed file found, ", lzname);
+
+                               outbuf = extract_lz_file(fent->start, &outlen, 0);
+                               write_file(extracted_file((char*)lzname), outbuf, outlen);
+
+                               free(outbuf);
+                               free(lzname);
+                       } else if (!strcmp(fent->name, "firmware")) {
+                               unsigned char *lzpos;
+                               char lzname[128];
+
+                               bzero(lzname, sizeof(lzname));
+                               strcpy(lzname, "firmware.");
+
+                               lzpos = fent->start + *((unsigned int*)(fent->start + 0x20));
+                               memcpy(lzname + strlen(lzname), lzpos - 4, 4);
+                               lzpos += 4;
+                               if (*((unsigned int*)(lzpos)) == LZ_MAGIC) {
+                                       unsigned char *outbuf;
+                                       unsigned int outlen;
+
+                                       printf("%s: compressed firmware part found", lzname);
+                                       outbuf = extract_lz_file(lzpos, &outlen, 1);
+                                       printf(", ");
+                                       write_file(extracted_file((char*)lzname), outbuf, outlen);
+
+                                       free(outbuf);
+                               }
+                       }
+               } else {
+                       printf(", ignoring...\n");
+               }
+               fent = get_next_file(NULL, 0);
+       }
+}
+
+void replace_add_file(unsigned char *fw, int len, char *fwname, char *lname)
+{
+       fprintf(stderr, "%s: Implement me!\n", __func__);
+       exit(1);
+}
+
+void list_files(unsigned char *fw, int len)
+{
+       struct file_entry *fent;
+
+       for (fent = get_next_file(fw, len); fent != NULL; fent = get_next_file(NULL, 0)) {
+               printf("0x%x %8d %s\n", fent->unknown, fent->length, fent->name);
+       }
+
+}
+
+void mkdir_p(char *dir)
+{
+       char *copy, *parent;
+
+       if ((dir == NULL) || (!strcmp(dir, ".")))
+               return;
+
+       if ((copy = strdup(dir)) == NULL) {
+               perror("strdup");
+               exit(1);
+       }
+       parent = dirname(copy);
+       mkdir_p(parent);
+
+       errno = 0;
+       if (mkdir(dir, 0755) == -1) {
+               if (errno != EEXIST) {
+                       fprintf(stderr, "%s: ", dir);
+                       perror("mkdir");
+                       exit(1);
+               }
+       }
+       free(copy);
+}
+
+void write_file(char *fname, unsigned char *buf, int len)
+{
+       char *filename_c, *dirn;
+       int fd;
+       int remaining;
+       int ret;
+
+       if ((filename_c = strdup(fname)) == NULL) {
+               perror("strdup");
+               exit(1);
+       }
+       dirn = dirname(filename_c);
+       mkdir_p(dirn);
+       free(filename_c);
+
+       if ((fd = open(fname, O_WRONLY|O_CREAT, 0644)) == -1) {
+               fprintf(stderr, "%s: ", fname);
+               perror("open");
+               exit(1);
+       }
+
+       remaining = len;
+
+       while(remaining) {
+               ret = write(fd, buf + (len - remaining), remaining);
+               if (ret < 0) {
+                       perror("write");
+                       exit(1);
+               }
+               remaining -= ret;
+       }
+
+       printf("%s written.\n", fname);
+
+       close(fd);
+}
+
+char *extracted_file(char *fname)
+{
+       static char filename[PATH_MAX];
+
+       strcpy(filename, "extracted/");
+       strcat(filename, fname);
+
+       return filename;
+}
diff --git a/src/filesystem.h b/src/filesystem.h
new file mode 100644 (file)
index 0000000..bf9a4c8
--- /dev/null
@@ -0,0 +1,13 @@
+struct file_entry {
+       char *name;
+       unsigned char *start;
+       int length;
+       unsigned char unknown;
+};
+
+struct file_entry* get_next_file(unsigned char *fw, int len);
+void extract_files(unsigned char *fw, int len);
+void replace_add_file(unsigned char *fw, int len, char *fwname, char *lname);
+void list_files(unsigned char *fw, int len);
+void write_file(char *fname, unsigned char *buf, int len);
+char *extracted_file(char *fname);
diff --git a/src/firmware.c b/src/firmware.c
new file mode 100644 (file)
index 0000000..b575012
--- /dev/null
@@ -0,0 +1,530 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <strings.h>
+#include "rsb-crc.h"
+#include "filesystem.h"
+
+#define FINDSTR(addr, str) (!strncmp((char*)addr, str, strlen(str)))
+
+struct properties {
+       unsigned int magic;
+       unsigned char unknown0;
+       unsigned char unknown1;
+       unsigned char right_rw;
+       unsigned char rw_mask;
+       unsigned char type1;
+       unsigned char unknown5;
+       unsigned char unknown6;
+       unsigned char unknown7;
+       unsigned char type2;
+       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)
+{
+       struct file_entry *fent;
+
+       for (fent = get_next_file(fw, len); fent != NULL; fent = get_next_file(NULL, 0)) {
+               if (FINDSTR(fent->name, "/default/fw_prop/") ||
+                   FINDSTR(fent->name, "/default/fw_setup/") ||
+                   FINDSTR(fent->name, "/default/oem_prop/")) {
+                       struct properties *prop;
+
+                       printf("0x%08x: found setting: %s ", fent->start - fw, fent->name);
+
+                       prop = (struct properties*)fent->start;
+                       
+                       if (prop->magic != 0x83011111) {
+                               printf("ignoring...\n");
+                               continue;
+                       }
+
+                       if (prop->type1 == 0x00 && prop->type2 == 0x04) {
+                               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) {
+                               printf("VAL: 0x%x ", *((unsigned int*)prop->val));
+                       } else {
+                               printf("0x%02x 0x%2x...ignoring\n", prop->type1, prop->type2);
+                               continue;
+                       }
+
+                       if (prop->right_rw == 0x00 && prop->rw_mask == 0x00) {
+                               printf("(R-)");
+                       } else if (prop->right_rw == 0x01) {
+                               printf("(RW mask: 0x%02x)", prop->rw_mask);
+                       } else {
+                               printf("(UNK 0x%02x 0x%02x)", prop->right_rw, prop->rw_mask);
+                       }
+                       printf(", length: %d\n", fent->length);
+               }
+       }
+}
+
+void change_properties(unsigned char *fw, int len, struct propaction *paction)
+{
+       struct file_entry *fent;
+       struct propaction *cpaction;
+
+       for (fent = get_next_file(fw, len); fent != NULL; fent = get_next_file(NULL, 0)) {
+               cpaction = paction;
+               while (cpaction != NULL) {
+                       if (FINDSTR(fent->name, cpaction->property)) {
+                               break;
+                       }
+                       cpaction = cpaction->next;
+               }
+               if (cpaction != NULL) {
+                       struct properties *prop;
+
+                       prop = (struct properties*)fent->start;
+
+                       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;
+                               }
+                       }
+               }
+       }
+}
+
+#define BD_SERIAL1     0x14,0x02
+#define BD_ICMB                0x14,0x04
+#define BD_LAN         0x14,0x08
+#define BD_SERIAL2     0x14,0x10
+#define BD_SERIAL3     0x14,0x20
+#define BD_USB         0x14,0x40
+#define BD_PCI         0x15,0x03
+#define BD_LPC         0x15,0x04
+#define BD_VGA         0x15,0x08
+#define BD_BATTERY     0x15,0x10
+#define BD_ACDC                0x15,0x20
+#define BD_STANDBY     0x15,0x40
+#define BD_POWERCONN   0x15,0x70
+#define BD_DVI         0x15,0x80
+#define BD_PWRATX      0x16,0x01
+#define BD_PWRRELAY    0x16,0x02
+#define BD_PS2A                0x19,0xff
+
+#define MAGIC(fn, args...) fn(args)
+
+#define _BD_IS_SET(bd, byte, bits) (bd[byte] & bits)
+#define BD_IS_SET(bd, ident) MAGIC(_BD_IS_SET, bd, BD_##ident)
+#define BD_TEXT(bd, ident) (BD_IS_SET(bd, ident) ? "TRUE" : "FALSE")
+
+#define _BD_SET(bd, byte, bits) (bd[byte] |= bits)
+#define BD_SET(bd, ident) MAGIC(_BD_SET, bd, BD_##ident)
+
+void print_boarddescription(unsigned char *bd)
+{
+       int j;
+
+       for (j = 0; j < 32; j++) {
+               printf("%02x ", *(bd+j));
+       }
+       printf("\n");
+
+       /* com/agilent/rmc/amr/AmrMaster.class
+        * com/agilent/rmc/mgui/RmcPanel.class
+        * com/agilent/rmc/mgui/panels/AvrManualConfig.class
+        * com/agilent/rmc/mgui/panels/CardConf.jad
+        * com/agilent/rmc/mgui/panels/PowerMgmtConf.jad
+        * com/agilent/rmc/mgui/panels/RemoteDiskConf.jad
+        */
+       printf("\tserial1Present\t\t: %s\n", BD_TEXT(bd, SERIAL1));
+       printf("\ticmbPresent\t\t: %s\n", BD_TEXT(bd, ICMB));
+       printf("\tlanPresent\t\t: %s\n", BD_TEXT(bd, LAN));
+       printf("\tserial2Present\t\t: %s\n", BD_TEXT(bd, SERIAL2));
+       printf("\tserial3Present\t\t: %s\n", BD_TEXT(bd, SERIAL3));
+       printf("\tusbPresent\t\t: %s\n", BD_TEXT(bd, USB));
+       printf("\tpciPresent\t\t: %s\n", BD_TEXT(bd, PCI));
+       printf("\tlpcPresent\t\t: %s\n", BD_TEXT(bd, LPC));
+       printf("\tvgaPresent\t\t: %s\n", BD_TEXT(bd, VGA));
+       printf("\tbatteryPresent\t\t: %s\n", BD_TEXT(bd, BATTERY));
+       printf("\tacdcPresent\t\t: %s\n", BD_TEXT(bd, ACDC));
+       printf("\tstandbyPresent\t\t: %s\n", BD_TEXT(bd, STANDBY));
+       printf("\thasPowerConnectors\t: %s\n", BD_TEXT(bd, POWERCONN));
+       printf("\tdviPresent\t\t: %s\n", BD_TEXT(bd, DVI));
+       printf("\tpowerSwitchATX\t\t: %s\n", BD_TEXT(bd, PWRATX));
+       printf("\tpowerSwitchRelay\t: %s\n", BD_TEXT(bd, PWRRELAY));
+       /* 22 & 4 */
+       printf("\tps2aPresent\t\t: %s\n", BD_TEXT(bd, PS2A));
+}
+
+void handle_boarddescription(unsigned char *fw, int len, int patch)
+{
+       struct file_entry *fent;
+       unsigned char *pos;
+       
+       for (fent = get_next_file(fw, len); fent != NULL; fent = get_next_file(NULL, 0)) {
+               if (!strcmp(fent->name, "pdata"))
+                       break;
+       }
+
+       if (fent == NULL) {
+               fprintf(stderr, "pdata file not found, aborting!\n");
+               exit(1);
+       }
+
+
+       pos = fent->start;
+       /* MAGIC? */
+       if (*((unsigned int*)pos) != 0x00002802) {
+               fprintf(stderr, "pdata magic does not match, aborting!\n");
+               exit(1);
+       }
+
+       pos += 26;
+
+       /* MAGIC2? */
+       if (*((unsigned int*)pos) != 0x00500101) {
+               fprintf(stderr, "pdata magic2 does not match, aborting!\n");
+               exit(1);
+       }
+
+       if (patch) {
+               /* Enable ATX and relay power switching */
+               BD_SET(pos, PWRATX);
+               BD_SET(pos, PWRRELAY);
+       }
+
+       printf("0x%08x: BOARD_DESCRIPTION: ", fent->start - fw);
+       print_boarddescription(pos);
+}
+
+void syntax(char *name)
+{
+       fprintf(stderr,"Syntax: %s parameters firmware.bin\n", name);
+       fprintf(stderr,"parameters as follows:\n");
+       fprintf(stderr,"\t-d\t\t\tdisplay all properties of the image\n");
+       fprintf(stderr,"\t-u\t\t\tupdate checksum of the image\n");
+       fprintf(stderr,"\t-b\t\t\tmodify BOARD_DESCRIPTION for more power-switch options\n");
+       fprintf(stderr,"\t-e\t\t\textract files in firmware\n");
+       fprintf(stderr,"\t-l\t\t\tlist files in firmware\n");
+       fprintf(stderr,"\t-t property\t\tset 'property' to true\n");
+       fprintf(stderr,"\t-f property\t\tset 'property' to false\n");
+       fprintf(stderr,"\t-w property\t\tallow read-write access to 'property'\n");
+       fprintf(stderr,"\t-r property\t\tallow read-only access to 'property'\n");
+       fprintf(stderr,"\t-x fw_file=local_file\treplace or add fw_file with content of local_file\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;
+}
+
+void check_image(unsigned char *fw, int len)
+{
+       struct file_entry *fent;
+       char *last_name = NULL;
+
+       /* get_next_file will abort on error */
+       fent = get_next_file(fw, len);
+       while (fent != NULL) {
+               last_name = fent->name;
+               fent = get_next_file(NULL, 0);
+       }
+}
+
+int main(int argc, char **argv)
+{
+       struct stat statbuf;
+       char *file = NULL;
+       unsigned char *fw;
+       int fd;
+       int remaining;
+       int ret;
+       int opt;
+       unsigned int crc;
+       struct propaction *paction = NULL;
+       int showall = 0;
+       int update_crc = 0;
+       int patch_bd = 0;
+       int patch_fw = 0;
+       int extract = 0;
+       int list = 0;
+
+       if (argc < 2)
+               syntax(argv[0]);
+
+       while ((opt = getopt(argc, argv, "dubelt:f:w:r:x:")) != -1) {
+               switch(opt) {
+                       case 'd':
+                               showall = 1;
+                               break;
+                       case 'u':
+                               update_crc = 1;
+                               break;
+                       case 'b':
+                               patch_bd = 1;
+                               break;
+                       case 'e':
+                               extract = 1;
+                               break;
+                       case 'l':
+                               list = 1;
+                               break;
+                       case 't':
+                       case 'f':
+                       case 'w':
+                       case 'r':
+                               patch_fw = 1;
+                               add_action(opt, optarg, &paction);
+                               break;
+                       case 'x':
+                               replace_add_file(NULL, 0, NULL, NULL);
+                               break;
+                       default:
+                               syntax(argv[0]);
+               }
+       }
+
+       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(file, O_RDONLY)) == -1) {
+               fprintf(stderr,"%s: ", file);
+               perror("open");
+               exit(1);
+       }
+
+       if ((fw = malloc(statbuf.st_size)) == NULL) {
+               perror("malloc");
+               exit(1);
+       }
+
+       bzero(fw, statbuf.st_size);
+
+       remaining = statbuf.st_size;
+
+       while(remaining) {
+               if ((ret = read(fd, fw + (statbuf.st_size - remaining), remaining)) == -1) {
+                       perror("read");
+                       exit(1);
+               }
+               remaining -= ret;
+       }
+       close(fd);
+
+       ret = check_crc(fw, statbuf.st_size);
+       if ((ret != 0) && (!update_crc)) {
+               fprintf(stderr,"Checksum incorrect, aborting...\n");
+               exit(1);
+       }
+
+       check_image(fw, statbuf.st_size - 4);
+
+       if (patch_fw) {
+               struct propaction *cpaction = paction;
+
+               change_properties(fw, statbuf.st_size - 4, 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 (patch_bd) {
+               handle_boarddescription(fw, statbuf.st_size - 4, 1);
+       }
+
+       if (showall) {
+               show_properties(fw, statbuf.st_size - 4);
+               handle_boarddescription(fw, statbuf.st_size - 4, 0);
+       }
+
+       if (list) {
+               list_files(fw, statbuf.st_size - 4);
+       }
+
+       if (extract) {
+               extract_files(fw, statbuf.st_size - 4);
+       }
+
+       if (update_crc || patch_fw || patch_bd) {
+               ret = rsb_crc2(fw, statbuf.st_size, 0x55335053, &crc);
+               if (ret == 4) {
+                       *((unsigned int*)(fw + statbuf.st_size - 4)) = crc;
+               }
+
+               check_image(fw, statbuf.st_size-4);
+
+               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("Firmware ");
+                       write_file(newfile, fw, statbuf.st_size);
+               } else {
+                       fprintf(stderr,"Can't set correct checksum, aborting...\n");
+               }
+       }
+       
+       exit(0);
+}
diff --git a/src/rsb-crc.c b/src/rsb-crc.c
new file mode 100644 (file)
index 0000000..6a2bf99
--- /dev/null
@@ -0,0 +1,54 @@
+#include <stdio.h>
+
+#define POLY 0x04c11db7
+
+unsigned int rsb_crc(unsigned int r11_crc, unsigned char *r10_buf, unsigned int r14_len) {
+       unsigned int r6_pos = 0;
+       unsigned int r3_data;
+       int r5_bit;
+
+       while (r6_pos < r14_len) {
+               r3_data = (*(r6_pos+r10_buf)) << 24;
+               r11_crc = r11_crc ^ r3_data;
+
+               r5_bit = 8;
+               
+               do {
+                       r3_data = r11_crc & 0x80000000;
+
+                       if (r3_data != 0) {
+                               r3_data = r11_crc << 1;
+                               r11_crc = r3_data ^ POLY;
+                       } else {
+                               r11_crc = r11_crc << 1;
+                       }
+                       r5_bit--;
+               } while (r5_bit);
+
+               r6_pos++;
+       }
+
+       return r11_crc;
+}
+
+unsigned int rsb_crc2(unsigned char *r0_buf, unsigned int r1_buflen, unsigned int r2_magic, unsigned int *crc_out) {
+       unsigned int r4_len;
+       unsigned int file_crc;
+
+       r4_len = *(unsigned int*)(r0_buf + 0x20);
+
+       if (*((unsigned int*)(r0_buf + 0x24)) != r2_magic)
+               return 2; /* MAGIC does not match */
+       
+       if (r1_buflen < r4_len)
+               return 3; /* image to small */
+       
+       *crc_out = ~rsb_crc(~0x0, r0_buf, r4_len);
+
+       file_crc = *((unsigned int*)(r0_buf + r4_len));
+
+       if (file_crc != *crc_out)
+               return 4;
+
+       return 0;
+}
diff --git a/src/rsb-crc.h b/src/rsb-crc.h
new file mode 100644 (file)
index 0000000..f97e6da
--- /dev/null
@@ -0,0 +1,2 @@
+unsigned int rsb_crc(unsigned int r11_crc, unsigned char *r10_buf, unsigned int r14_len);
+unsigned int rsb_crc2(unsigned char *r0_buf, unsigned int r1_buflen, unsigned int r2_magic, unsigned int *crc_out);
diff --git a/src/rsb-lz.c b/src/rsb-lz.c
new file mode 100644 (file)
index 0000000..bb735d6
--- /dev/null
@@ -0,0 +1,316 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include "rsb-crc.h"
+#include "rsb-lz.h"
+#include "filesystem.h"
+
+void err_exit(const char *fname)
+{
+       fprintf(stderr,"%s: error extracting...\n", fname);
+       exit(1);
+}
+
+struct data_in_s {
+       unsigned char *start;
+       unsigned char *stop;
+       unsigned char bitpos;
+       unsigned char byte;
+};
+
+struct data_out_s {
+       unsigned char *pos;
+       unsigned char *end;
+};
+
+unsigned char get_next_in_byte(struct data_in_s *data_in)
+{
+       unsigned char byte;
+
+       if (data_in->stop < data_in->start)
+               err_exit(__func__);
+
+       byte = *(data_in->start);
+       data_in->start++;
+
+       return byte;
+}
+
+unsigned char get_next_bit(struct data_in_s *data_in)
+{
+       unsigned char bitval;
+
+       if (data_in->bitpos == 0x80) {
+               data_in->byte = get_next_in_byte(data_in);
+       }
+
+       bitval = data_in->bitpos & data_in->byte;
+
+       data_in->bitpos >>= 1;
+       if (data_in->bitpos == 0) {
+               data_in->bitpos = 0x80;
+       }
+
+       if (bitval == 0)
+               return 0;
+
+       return 1;
+}
+
+unsigned int get_next_bits(struct data_in_s *data_in, unsigned int bits)
+{
+       unsigned int bit;
+       unsigned int next_bits;
+
+       bit = 1 << (bits - 1);
+
+       next_bits = 0;
+       while (bit != 0) {
+               if (data_in->bitpos == 0x80) {
+                       data_in->byte = get_next_in_byte(data_in);
+               }
+
+               if ((data_in->bitpos & data_in->byte) != 0)
+                       next_bits = next_bits | bit;
+
+               bit = bit >> 1;
+
+               data_in->bitpos >>= 1;
+
+               if(data_in->bitpos == 0) {
+                       data_in->bitpos = 0x80;
+               }
+       }
+
+       return next_bits;
+}
+
+void write_byte(unsigned char byte, struct data_out_s *data_out)
+{
+       if (data_out->pos > data_out->end) {
+               err_exit(__func__);
+       }
+
+       *(data_out->pos) = byte;
+       data_out->pos++;
+}
+
+void lz_expand(struct data_in_s *data_in, struct data_out_s *data_out)
+{
+       unsigned int pos;
+       unsigned int wordoffset;
+       unsigned int i;
+       unsigned char byte;
+       unsigned int wordlen;
+       unsigned char buf[1024];
+
+       pos = 1;
+
+       while (1) {
+               while (1) {
+                       /* Compressed/uncompressed? */
+                       if (get_next_bit(data_in) == 0)
+                               break;
+
+                       /* Uncompressed byte */
+                       byte = get_next_bits(data_in, 8);
+
+                       write_byte(byte, data_out);
+
+                       /* Save byte in buffer, to be reused later */
+                       buf[pos] = byte;
+                       pos = (pos + 1) & 0x3ff;
+               }
+
+               /* offset for start of dictionary word */
+               wordoffset = get_next_bits(data_in, 0x0a);
+               if(wordoffset == 0)
+                       return;
+
+               /* length of dictionary word used */
+               wordlen = get_next_bits(data_in, 0x04) + 1;
+               for (i = 0; i <= wordlen ; i++) {
+                       /* lookup dictionary byte */
+                       byte = buf[(wordoffset + i) & 0x3ff];
+                       write_byte(byte, data_out);
+                       /* Save byte in buffer, to be reused later */
+                       buf[pos] = byte;
+                       pos = (pos + 1) & 0x3ff;
+               }
+       }
+}
+
+void set_next_bit(unsigned char *buf, unsigned int set, unsigned int *currbit) {
+       unsigned char *pos;
+       unsigned char bitpos;
+
+       if (set) {
+               pos = buf + ((*currbit) / 8);
+               bitpos = 0x80 >> ((*currbit) % 8);
+               *pos |= bitpos;
+       }
+
+       *currbit = *currbit + 1;
+}
+
+void write_bits(unsigned char *buf, unsigned int data, unsigned int bits, unsigned int *currbit) {
+       int i;
+       unsigned int bitpos;
+
+       bitpos = 1 << (bits - 1);
+
+       for (i = 0; i < bits; i++) {
+               set_next_bit(buf, data & bitpos, currbit);
+               bitpos >>= 1;
+       }
+}
+
+unsigned char *compress_lz(unsigned char *inbuf, int inlen, int *outlen)
+{
+       unsigned char *end = inbuf + inlen;
+       unsigned char *outbuf;
+       unsigned char window[1024];
+       int pos = 0;
+       int fill = 0;
+       unsigned int currbit = 0;
+       int offset;
+       int wordlen;
+       int found;
+       int i;
+
+       if ((outbuf = malloc((inlen * 2) + 4)) == NULL) {
+               perror("malloc");
+       }
+
+       *((unsigned int*)outbuf) = LZ_MAGIC;
+       currbit = 8 * 8;
+
+       while(inbuf < end) {
+               found = 0;
+               for (wordlen = 17; wordlen > 1; wordlen--) {
+                       for (offset = 1; offset < ((fill < 1023) ? fill : 1023); offset++) {
+                               if ((fill < 1023) &&
+                                   (wordlen + offset > fill))
+                                       break;
+
+                               for (i = 0; i < wordlen; i++) {
+                                       if (inbuf[i] != window[(offset + i) & 0x3ff]) {
+                                               break;
+                                       }
+                               }
+                               if (i == wordlen)
+                                       found = 1;
+                       }
+                       if (found)
+                               break;
+               }
+
+               if (found) {
+                       write_bits(outbuf, 0x00, 0x01, &currbit);
+                       write_bits(outbuf, offset, 0x0a, &currbit);
+                       write_bits(outbuf, wordlen - 1, 0x04, &currbit);
+                       for (i = 0; i < wordlen; i++) {
+                               window[pos] = *(inbuf + i);
+                               pos = (pos + 1) & 0x3ff;
+                       }
+                       inbuf += wordlen;
+
+                       if (fill < sizeof(window))
+                               fill += wordlen;
+               } else {
+                       write_bits(outbuf, 0x01, 0x01, &currbit);
+                       write_bits(outbuf, *inbuf, 0x08, &currbit);
+                       window[pos] = *inbuf;
+                       pos = (pos + 1) & 0x3ff;
+                       inbuf++;
+                       if (fill < sizeof(window))
+                               fill++;
+               }
+       }
+
+       write_bits(outbuf, 0x00, 0x01, &currbit);
+       write_bits(outbuf, 0x00, 0x0a, &currbit);
+
+       *outlen = (currbit / 8) + 1;
+
+       *((unsigned int*)(outbuf + 4)) = *outlen;
+
+       return outbuf;
+}
+
+/* Checksum is only used for the compressed firmware in 'firmware' */
+unsigned int crc_check(unsigned char *buf, unsigned int len, unsigned int magic)
+{
+       unsigned int file_crc;
+       unsigned int my_len;
+       unsigned int crc;
+       unsigned int my_magic;
+
+       my_len = *((unsigned int*)(buf + 0x20));
+       my_magic = *((unsigned int*)(buf + 0x24));
+
+       if (my_magic != magic) {
+               printf("\nmagic: 0x%08x <-> 0x%08x\n", my_magic, magic);
+               return 2;
+       }
+       
+       if (len < my_len)
+               return 3;
+
+       crc = ~rsb_crc(~0x00, buf, len);
+       file_crc = *((unsigned int*)(buf + len));
+
+       if (file_crc != crc) {
+               printf("\nChecksums: 0x%08x <-> 0x%08x!\n", crc, file_crc);
+               return 4;
+       }
+
+       return 0;
+}
+
+unsigned char *extract_lz_file(unsigned char *inbuf, unsigned int *outlen , unsigned char check_crc)
+{
+       unsigned char *outbuf;
+       struct data_in_s data_in;
+       struct data_out_s data_out;
+
+       if (*((unsigned int*)inbuf) != LZ_MAGIC)
+               err_exit(__func__);
+
+       *outlen = *((unsigned int*)(inbuf + 4));
+       printf(", length: %d", *outlen);
+
+       if ((outbuf = malloc(*outlen)) == NULL) {
+               perror("malloc");
+               exit(1);
+       }
+
+       bzero(outbuf, *outlen);
+
+       data_in.start = inbuf + 8;
+       data_in.stop = inbuf + *outlen;
+       data_in.byte = 0x00;
+       data_in.bitpos = 0x80;
+
+       data_out.pos = outbuf;
+       data_out.end = outbuf + *outlen;
+
+       lz_expand(&data_in, &data_out);
+
+       if (check_crc) {
+               unsigned int crclen;
+               int ret;
+
+               crclen = *((unsigned int*)(outbuf + 0x20));
+
+               if ((ret = crc_check(outbuf, crclen, 0x46335053)) != 0) {
+                       printf("crc_check return: %d\n", ret);
+                       err_exit(__func__);
+               }
+       }
+
+       return outbuf;
+}
diff --git a/src/rsb-lz.h b/src/rsb-lz.h
new file mode 100644 (file)
index 0000000..4cf2c82
--- /dev/null
@@ -0,0 +1,4 @@
+#define LZ_MAGIC 0x6110beef
+
+unsigned char *extract_lz_file(unsigned char *inbuf, unsigned int *outlen , unsigned char check_crc);
+unsigned char *compress_lz(unsigned char *inbuf, int inlen, int *outlen);
Impressum, Datenschutz