From: Michael Gernoth Date: Wed, 28 Jan 2009 11:32:08 +0000 (+0100) Subject: implement second agilent crc algorithm X-Git-Url: https://git.zerfleddert.de/cgi-bin/gitweb.cgi/rsbs2/commitdiff_plain/6fc57dcd5431aa5e19febfadb242de1e80f16c8f?hp=c8b1eccb76b5f4141da32b74c68468eaa87c7972 implement second agilent crc algorithm --- diff --git a/Makefile b/Makefile index 6122eea..6b43a5f 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -CFLAGS=-Wall +CFLAGS=-Wall -O3 all: firmware diff --git a/firmware.c b/firmware.c index f8584c1..67f1f0a 100644 --- a/firmware.c +++ b/firmware.c @@ -8,38 +8,6 @@ #include #include "rsb-crc.h" -struct fw_header { - unsigned int unknown[8]; - unsigned int len; - char ident[4]; - unsigned int offset; - char desc[128]; -}; - -void parse_fw(unsigned char *fw, unsigned int off) { - struct fw_header *header = (struct fw_header*)(fw + off); - static unsigned int last_off; - int i; - - printf("Address in file: 0x%08x, Difference to last: %u\n", off, off-last_off); - printf("Unknown: "); - for (i = 0; i < 8; i++) - printf("0x%08x ", header->unknown[i]); - - printf("\n"); - - printf("Length: %u, possible next entry at: 0x%08x\n", header->len, off + header->len + 22); - - printf("Identifier: %.4s\n", header->ident); - - printf("Offset: 0x%08x\n", header->offset); - - printf("Descriptiom: %s\n", header->desc); - - printf("\n"); - last_off = off; -} - int main(int argc, char **argv) { struct stat statbuf; @@ -47,7 +15,7 @@ int main(int argc, char **argv) int fd; int remaining; int ret; - unsigned int crc; + unsigned int crc, oldcrc; if (argc != 2) { fprintf(stderr,"Syntax: %s firmware.bin\n", argv[0]); @@ -81,15 +49,10 @@ int main(int argc, char **argv) remaining -= ret; } -#if 0 - parse_fw(fw, 0x0); - parse_fw(fw, 0x555c0); - parse_fw(fw, 0x5940e); -#endif - - crc = rsb_crc(0, fw, statbuf.st_size-4); + ret = rsb_crc2(fw, statbuf.st_size, 0x55335053, &crc); + oldcrc = (unsigned int)*((unsigned int*)(fw + statbuf.st_size - 4)); - printf("Length: %ld, Checksum: 0x%08x\n", statbuf.st_size-4, crc); + printf("Checksum: 0x%08x, should be: 0x%08x\n", crc, oldcrc); exit(0); } diff --git a/rsb-crc.c b/rsb-crc.c index fa40c49..3fe5cbc 100644 --- a/rsb-crc.c +++ b/rsb-crc.c @@ -1,7 +1,10 @@ +#include + #define POLY 0x04c11db7 /* Theory of operation: * (arm-elf-objdump -b binary -m arm -M reg-names-raw -D RSB_S2_SINGLE.bin) + * Addresses: 0x4c4, 0x55ae0, 0x59734 * * 440: push {r4, r5, r6, r7, r8, r9, r10, r11, r14} * 444: mov r11, r0 @@ -62,3 +65,129 @@ unsigned int rsb_crc(unsigned int r11_crc, unsigned char *r10_buf, unsigned int return r11_crc; } + +/* Second broken algorithm: + * + * 55a30: push {r3, r4, r5, r6, r7, r8, r9, r14} + * 55a34: bl 0x55a3c + * 55a38: pop {r3, r4, r5, r6, r7, r8, r9, r15} + * 55a3c: mov r8, #1 ; 0x1 + * 55a40: mov r3, #-1073741824 ; 0xc0000000 + * 55a44: cmp r0, r3 + * 55a48: ble 0x55ad8 + * 55a4c: mov r3, #32 ; 0x20 + * 55a50: ldr r4, [r3, r0]! + * 55a54: mov r8, #2 ; 0x2 + * 55a58: ldr r5, [r3, #4] + * 55a5c: cmp r5, r2 + * 55a60: bne 0x55ad8 + * 55a64: mov r8, #3 ; 0x3 + * 55a68: cmp r1, r4 + * 55a6c: movscs r5, #0 ; 0x0 + * 55a70: movscc r5, #1 ; 0x1 + * 55a74: bne 0x55ad8 + * 55a78: mov r8, #4 ; 0x4 + * 55a7c: mov r3, r0 + * 55a80: add r4, r0, r4 + * 55a84: mvn r5, #0 ; 0x0 + * 55a88: ldr r7, [pc, #80] ; 0x55ae0 + * 55a8c: cmp r3, r4 + * 55a90: bcs 0x55ac8 + * 55a94: bic r9, r3, #3 ; 0x3 + * 55a98: ldr r6, [r9] + * 55a9c: and r9, r3, #3 ; 0x3 + * 55aa0: lsl r9, r9, #3 + * 55aa4: lsr r6, r6, r9 + * 55aa8: eor r5, r5, r6, lsl #24 + * 55aac: mov r6, #8 ; 0x8 + * 55ab0: lsls r5, r5, #1 + * 55ab4: eorcs r5, r5, r7 + * 55ab8: subs r6, r6, #1 ; 0x1 + * 55abc: bne 0x55ab0 + * 55ac0: add r3, r3, #1 ; 0x1 + * 55ac4: b 0x55a8c + * 55ac8: mvn r5, r5 + * 55acc: ldr r3, [r4] + * 55ad0: subs r3, r3, r5 + * 55ad4: moveq r8, #0 ; 0x0 + * 55ad8: mov r0, r8 + * 55adc: mov r15, r14 + * 55ae0: DATA: 0x04c11db7 + */ + +unsigned int rsb_crc2(unsigned char *r0_buf, unsigned int r1_buflen, unsigned int r2_magic, unsigned int *crc) { + int r8_ret = 1; + unsigned int r3 = 0xc0000000; + unsigned int r4_len; + unsigned int r5; + unsigned int r6; + unsigned int r7_poly; + unsigned int r9; + unsigned int carry; + +#if 0 + if (r0_buf <= r3) + return r8_ret; +#endif + + r3 = ((unsigned int)r0_buf) + 0x20; + r4_len = *((unsigned int*)r3); + printf("CRC: length: %d\n", r4_len); + + r8_ret = 2; + + r3 += 4; + r5 = *((unsigned int*)r3); + + if (r5 != r2_magic) + return r8_ret; + + r8_ret = 3; + + if (r1_buflen >= r4_len) { + r5 = 0; + } else { + r5 = 1; + } + + if (r5 != 0) + return r8_ret; + + r8_ret = 4; + + r3 = (unsigned int)r0_buf; + r4_len += r3; + + r5 = ~0x0; + + r7_poly = POLY; + + while (r3 < r4_len) { + r9 = r3 & (~0x3); + r6 = *((unsigned int*)r9); + r9 = r3 & 0x3; + r9 = r9 << 0x3; + r6 = r6 >> r9; + r5 = r5 ^ (r6 << 24); + r6 = 0x8; + + do { + carry = r5 & 0x80000000; + r5 = r5 << 1; + if (carry) + r5 = r5 ^ r7_poly; + r6--; + } while(r6); + r3++; + } + + r5 = ~r5; + *crc = r5; + + r3 = *((unsigned int*)r4_len); + + if (r3 == r5) + r8_ret = 0; + + return r8_ret; +} diff --git a/rsb-crc.h b/rsb-crc.h index 94d327d..c59ccde 100644 --- a/rsb-crc.h +++ b/rsb-crc.h @@ -1 +1,2 @@ -unsigned int rsb_crc(unsigned int r11, unsigned char *r10, unsigned int r14); +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);