From: Michael Gernoth Date: Sat, 6 Mar 2010 10:23:06 +0000 (+0100) Subject: move source files to own subdirectory X-Git-Url: https://git.zerfleddert.de/cgi-bin/gitweb.cgi/rsbs2/commitdiff_plain/05b6bf30040b7d3f2219919168b4c159045a909b move source files to own subdirectory --- diff --git a/.gitignore b/.gitignore index b861e4c..1f5a488 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,2 @@ -filesystem.o firmware -firmware.o -rsb-crc.o -rsb-lz.o extracted diff --git a/Makefile b/Makefile index 15de0a8..8517dff 100644 --- 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 index d644679..0000000 --- a/filesystem.c +++ /dev/null @@ -1,232 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#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 index bf9a4c8..0000000 --- a/filesystem.h +++ /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 index b575012..0000000 --- a/firmware.c +++ /dev/null @@ -1,530 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#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 index 6a2bf99..0000000 --- a/rsb-crc.c +++ /dev/null @@ -1,54 +0,0 @@ -#include - -#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 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 index bb735d6..0000000 --- a/rsb-lz.c +++ /dev/null @@ -1,316 +0,0 @@ -#include -#include -#include -#include -#include -#include -#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 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 index 0000000..8112a8e --- /dev/null +++ b/src/.gitignore @@ -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 index 0000000..15de0a8 --- /dev/null +++ b/src/Makefile @@ -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 index 0000000..d644679 --- /dev/null +++ b/src/filesystem.c @@ -0,0 +1,232 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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 index 0000000..bf9a4c8 --- /dev/null +++ b/src/filesystem.h @@ -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 index 0000000..b575012 --- /dev/null +++ b/src/firmware.c @@ -0,0 +1,530 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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 index 0000000..6a2bf99 --- /dev/null +++ b/src/rsb-crc.c @@ -0,0 +1,54 @@ +#include + +#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 index 0000000..f97e6da --- /dev/null +++ b/src/rsb-crc.h @@ -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 index 0000000..bb735d6 --- /dev/null +++ b/src/rsb-lz.c @@ -0,0 +1,316 @@ +#include +#include +#include +#include +#include +#include +#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 index 0000000..4cf2c82 --- /dev/null +++ b/src/rsb-lz.h @@ -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);