From: Michael Gernoth Date: Tue, 27 Jan 2009 23:49:19 +0000 (+0100) Subject: add something like the agilent crc implementation X-Git-Url: https://git.zerfleddert.de/cgi-bin/gitweb.cgi/rsbs2/commitdiff_plain/972ac24b5466e95d78f4af724c2f4e197f340eb5 add something like the agilent crc implementation --- diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6fe1a09 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +firmware +firmware.o +rsb-crc.o diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..6122eea --- /dev/null +++ b/Makefile @@ -0,0 +1,14 @@ +CFLAGS=-Wall + +all: firmware + +firmware: firmware.o rsb-crc.o + +firmware.o: firmware.c rsb-crc.h + +rsb-crc.o: rsb-crc.c rsb-crc.h + +clean: + rm -f firmware firmware.o rsb-crc.o + +.PHONY: all clean diff --git a/firmware.c b/firmware.c new file mode 100644 index 0000000..f8584c1 --- /dev/null +++ b/firmware.c @@ -0,0 +1,95 @@ +#include +#include +#include +#include +#include +#include +#include +#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; + unsigned char *fw; + int fd; + int remaining; + int ret; + unsigned int crc; + + if (argc != 2) { + fprintf(stderr,"Syntax: %s firmware.bin\n", argv[0]); + exit(1); + } + + if (stat(argv[1], &statbuf) == -1) { + perror("stat"); + exit(1); + } + + if ((fd = open(argv[1], O_RDONLY)) == -1) { + 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; + } + +#if 0 + parse_fw(fw, 0x0); + parse_fw(fw, 0x555c0); + parse_fw(fw, 0x5940e); +#endif + + crc = rsb_crc(0, fw, statbuf.st_size-4); + + printf("Length: %ld, Checksum: 0x%08x\n", statbuf.st_size-4, crc); + + exit(0); +} diff --git a/rsb-crc.c b/rsb-crc.c new file mode 100644 index 0000000..84b7fa2 --- /dev/null +++ b/rsb-crc.c @@ -0,0 +1,64 @@ +#define POLY 0x04c11db7 + +/* Theory of operation: + * (arm-elf-objdump -b binary -m arm -M reg-names-raw -D RSB_S2_SINGLE.bin) + * + * 440: push {r4, r5, r6, r7, r8, r9, r10, r11, r14} + * 444: mov r11, r0 + * 448: mov r10, r1 + * 44c: mov r14, r2 + * 450: mov r6, #0 ; 0x0 + * 454: b 0x4a0 + * 458: add r3, r6, r10 + * 45c: ldrb r3, [r3] + * 460: lsl r3, r3, #24 + * 464: eor r11, r11, r3 + * 468: mov r5, #8 ; 0x8 + * 46c: and r3, r11, #-2147483648 ; 0x80000000 + * 470: cmp r3, #0 ; 0x0 + * 474: beq 0x48c + * 478: lsl r3, r11, #1 + * 47c: ldr r12, [pc, #64] ; 0x4c4 + * 480: eor r0, r3, r12 + * 484: mov r11, r0 + * 488: b 0x490 + * 48c: lsl r11, r11, #1 + * 490: sub r5, r5, #1 ; 0x1 + * 494: cmp r5, #0 ; 0x0 + * 498: bne 0x46c + * 49c: add r6, r6, #1 ; 0x1 + * 4a0: cmp r6, r14 + * 4a4: blt 0x458 + * 4a8: mov r0, r11 + * 4ac: pop {r4, r5, r6, r7, r8, r9, r10, r11, r15} + * 4c4: DATA: 0x04c11db7 + */ + +unsigned int rsb_crc(unsigned int r11, unsigned char *r10, unsigned int r14) { + unsigned int r6 = 0; + unsigned int r3; + int r5; + + while (r6 < r14) { + r3 = (*(r6+r10)) << 24; + r11 = r11 ^ r3; + + r5 = 8; + + do { + r3 = r11 & 0x80000000; + + if (r3 != 0) { + r3 = r11 << 1; + r11 = r3 ^ POLY; + } else { + r11 = r11 << 1; + } + r5--; + } while (r5); + + r6++; + } + + return r11; +} diff --git a/rsb-crc.h b/rsb-crc.h new file mode 100644 index 0000000..94d327d --- /dev/null +++ b/rsb-crc.h @@ -0,0 +1 @@ +unsigned int rsb_crc(unsigned int r11, unsigned char *r10, unsigned int r14);