# HG changeset patch # User Mychaela Falconia # Date 1482709696 0 # Node ID d69f7512e3c152b180670807568144fdb14b063c # Parent 6b40617d00e600bf1108b385faf12e31af0e87ad Pirelli: documented and verified the checksum scheme used for the factory block diff -r 6b40617d00e6 -r d69f7512e3c1 .hgignore --- a/.hgignore Tue Jul 26 23:32:17 2016 +0000 +++ b/.hgignore Sun Dec 25 23:48:16 2016 +0000 @@ -34,6 +34,7 @@ ^miscprog/memwrite-grep$ ^miscprog/mokosrec2bin$ ^miscprog/pircksum$ +^miscprog/pircksum2$ ^miscprog/pirimei$ ^miscprog/rfcap-grep$ diff -r 6b40617d00e6 -r d69f7512e3c1 miscprog/Makefile --- a/miscprog/Makefile Tue Jul 26 23:32:17 2016 +0000 +++ b/miscprog/Makefile Sun Dec 25 23:48:16 2016 +0000 @@ -1,7 +1,7 @@ CC= gcc CFLAGS= -O2 STD= atsc calextract factdiff grokdsn memwrite-grep mokosrec2bin pircksum \ - rfcap-grep + pircksum2 rfcap-grep CRYPTO= imeibrute pirimei PROGS= ${STD} ${CRYPTO} @@ -21,6 +21,7 @@ memwrite-grep: memwrite-grep.c mokosrec2bin: mokosrec2bin.c pircksum: pircksum.c +pircksum2: pircksum2.c pirimei: pirimei.c rfcap-grep: rfcap-grep.c diff -r 6b40617d00e6 -r d69f7512e3c1 miscprog/pircksum2.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/miscprog/pircksum2.c Sun Dec 25 23:48:16 2016 +0000 @@ -0,0 +1,116 @@ +/* + * This program verifies the correctness of the understanding described in the + * ../pirelli/flash2-chksum write-up. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +char *image_filename; +u_char *image_map, *endrec; +unsigned imgsize, max_imgsize; + +open_and_map_file() +{ + int fd; + struct stat st; + + fd = open(image_filename, O_RDONLY); + if (fd < 0) { + perror(image_filename); + exit(1); + } + fstat(fd, &st); + if (!S_ISREG(st.st_mode)) { + fprintf(stderr, "error: %s is not a regular file\n", + image_filename); + exit(1); + } + if (st.st_size != 0x10000 && st.st_size != 0x360000) { + fprintf(stderr, "error: %s has an unexpected size\n", + image_filename); + exit(1); + } + max_imgsize = st.st_size - 12; + image_map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (image_map == MAP_FAILED) { + perror("mmap"); + exit(1); + } + close(fd); + endrec = image_map + max_imgsize; + return 0; +} + +verify_chksum1() +{ + uint16_t sum, ref; + unsigned offset; + + sum = 0; + for (offset = 0; offset + 1 < imgsize; offset += 2) + sum += le16toh(*(uint16_t *)(image_map + offset)); + if (imgsize & 1) + sum += image_map[offset]; + ref = le16toh(*(uint16_t *)(endrec + 8)); + if (sum == ref) { + printf("Checksum 1 matches (%04X)\n", sum); + return 0; + } else { + printf("Checksum 1 FAILED: computed %04X, stored %04X\n", + sum, ref); + return 1; + } +} + +verify_chksum2() +{ + uint16_t sum, ref; + unsigned offset; + + sum = 0; + for (offset = 0; offset < 10; offset += 2) + sum += le16toh(*(uint16_t *)(endrec + offset)); + ref = le16toh(*(uint16_t *)(endrec + 10)); + if (sum == ref) { + printf("Checksum 2 matches (%04X)\n", sum); + return 0; + } else { + printf("Checksum 2 FAILED: computed %04X, stored %04X\n", + sum, ref); + return 1; + } +} + +main(argc, argv) + char **argv; +{ + int stat1, stat2; + + if (argc != 2) { + fprintf(stderr, "usage: %s image-filename\n", argv[0]); + exit(1); + } + image_filename = argv[1]; + open_and_map_file(); + if (le32toh(*(uint32_t *)endrec) != 0x12345678) { + printf("Error: 0x12345678 signature missing\n"); + exit(1); + } + imgsize = le32toh(*(uint32_t *)(endrec + 4)); + if (imgsize < 1 || imgsize > max_imgsize) { + printf("Error: bogus image size of 0x%x bytes\n", imgsize); + exit(1); + } + printf("Image size: 0x%x bytes\n", imgsize); + stat1 = verify_chksum1(); + stat2 = verify_chksum2(); + exit(stat1 || stat2); +} diff -r 6b40617d00e6 -r d69f7512e3c1 pirelli/flash2-chksum --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pirelli/flash2-chksum Sun Dec 25 23:48:16 2016 +0000 @@ -0,0 +1,33 @@ +Pirelli's flash usage scheme allocates 3 "magic" areas in the flash2 bank: + +offset 0x480000 thru 0x7DFFFF: staging area for high-level fw updates +offset 0x7E0000 thru 0x7EFFFF: fw update control/state structure +offset 0x7F0000 thru 0x7FFFFF: factory record with IMEI and RF calibration + +The image or record stored in each of these "magic" areas ends with the +following 12-byte signature and checksum structure: + +Offset[1] Type[2] Contains +xxFFF4 32-bit word 0x12345678 +xxFFF8 32-bit word Length of the fw update image or factory or + fw update state record +xxFFFC 16-bit word Checksum 1 +xxFFFE 16-bit word Checksum 2 + +[1] The offset is from the beginning of the flash partition in question, the + xx digits will be 35 in the case of the 0x360000 byte fw update staging + area partition or 00 in the case of the two 64 KiB sectors. + +[2] All 16-bit and 32-bit values are in little-endian byte order. + +Checksum computation +==================== + +The checksum is computed in two stages. First all 16-bit words in the main +body of the image (using the image length from the xxFFF8 word) are added +together as a ripple-carry sum, and this 16-bit sum is written into the 0xFFFC +word. Then the 5 16-bit words from xxFFF4 through xxFFFC (inclusive) are added +together (again as a ripple-carry sum), and this sum is written into the xxFFFE +word. Remember the little-endian byte order throughout! + +The ../miscprog/pircksum2.c program verifies this checksum computation scheme.