# HG changeset patch # User Michael Spacefalcon # Date 1373141794 0 # Node ID 15c2ac2c5c73ef2de186342d42e6e97cebf353b0 # Parent 86a494a5f2b03f7bd699f0a0f9d60ee71f695df2 pirollback: started diff -r 86a494a5f2b0 -r 15c2ac2c5c73 .hgignore --- a/.hgignore Fri Jul 05 03:26:06 2013 +0000 +++ b/.hgignore Sat Jul 06 20:16:34 2013 +0000 @@ -12,3 +12,5 @@ ^mysteryffs/dump[12]$ ^mysteryffs/extract$ ^mysteryffs/scan1$ + +^pirollback/analyze$ diff -r 86a494a5f2b0 -r 15c2ac2c5c73 pirollback/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pirollback/Makefile Sat Jul 06 20:16:34 2013 +0000 @@ -0,0 +1,13 @@ +CC= gcc +CFLAGS= -O2 +PROGS= analyze + +ANALYZE_OBJS= analyze.o init.o + +all: ${PROGS} + +analyze: ${ANALYZE_OBJS} + ${CC} -o $@ ${ANALYZE_OBJS} + +clean: + rm -f *.o *.out *errs ${PROGS} diff -r 86a494a5f2b0 -r 15c2ac2c5c73 pirollback/README --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pirollback/README Sat Jul 06 20:16:34 2013 +0000 @@ -0,0 +1,10 @@ +This program is a hack written in order to clean up the fallout from a +previous screw-up of mine. I have started using my first Pirelli phone +(the very first one I got from ebay, and its firmware version is different +from all the later ones I got) as my personal everyday phone before I made +a dump of its flash2 bank, which contains the FFS. As a result, the +earliest FFS dump I have for this phone is already contaminated with some +private personal information. I want to release this FFS image on my FTP +site along with the firmware version it goes with, but first I need to +"roll it back" to a point just before it got dirtied with the non-releasable +personal info. This hack-program seeks to accomplish the feat. diff -r 86a494a5f2b0 -r 15c2ac2c5c73 pirollback/analyze.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pirollback/analyze.c Sat Jul 06 20:16:34 2013 +0000 @@ -0,0 +1,19 @@ +#include +#include + +extern char *imgfile; +extern int last_inode; + +main(argc, argv) + char **argv; +{ + if (argc != 2) { + fprintf(stderr, "usage: %s ffs-image\n", argv[0]); + exit(1); + } + imgfile = argv[1]; + read_img_file(); + read_inodes(); + printf("Last inode is #%x\n", last_inode); + exit(0); +} diff -r 86a494a5f2b0 -r 15c2ac2c5c73 pirollback/init.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pirollback/init.c Sat Jul 06 20:16:34 2013 +0000 @@ -0,0 +1,113 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "types.h" +#include "struct.h" + +u8 blank_flash_line[16] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + +char *imgfile; +u8 image[0x480000]; +struct inode_info inode[0x4000]; +int last_inode; + +static u8 magichdr_first[9] = {'F','f','s','#', 0x10, 0x02, 0xFF, 0xFF, 0xAB}; +static u8 magichdr_mid[9] = {'F','f','s','#', 0x10, 0x02, 0xFF, 0xFF, 0xBD}; +static u8 magichdr_last[9] = {'F','f','s','#', 0x10, 0x02, 0xFF, 0xFF, 0xBF}; + +read_img_file() +{ + int i, fd, cc; + u8 *blk, *compare; + + fd = open(imgfile, O_RDONLY); + if (fd < 0) { + perror(imgfile); + exit(1); + } + cc = read(fd, image, sizeof image); + close(fd); + if (cc != sizeof image) { +inv: fprintf(stderr, + "%s does not appear to be a \"virgin\" Pirelli FFS image\n", + imgfile); + exit(1); + } + for (i = 0; i < 18; i++) { + blk = image + i * 0x40000; + if (i == 0) + compare = magichdr_first; + else if (i == 17) + compare = magichdr_last; + else + compare = magichdr_mid; + if (bcmp(blk, compare, 9)) + goto inv; + } +} + +static int +convert_ptr(ptr, ino, which) + int ptr, ino; + char *which; +{ + if (ptr >= 1 && ptr <= 0x3FFF) + return(ptr); + if (ptr == 0xFFFF) + return(0); + fprintf(stderr, "error in inode #%x: invalid %s pointer\n", ino, which); + exit(1); +} + +read_inodes() +{ + int ino; + struct inode_flash *fl; + struct inode_info *inf; + + for (ino = 1; ino < 0x4000; ino++) { + fl = (struct inode_flash *) image + ino; + if (!bcmp(fl, blank_flash_line, 16)) + break; + inf = inode + ino; + inf->flash = fl; + inf->len = le16toh(fl->len); + if (!inf->len) { + fprintf(stderr, "error: inode %x has zero length\n", + ino); + exit(1); + } + if (inf->len & 0xF) { + fprintf(stderr, "error: inode %x has bad length\n", + ino); + exit(1); + } + inf->type = fl->type; + inf->descend = convert_ptr(le16toh(fl->descend), ino, + "descendant"); + inf->sibling = convert_ptr(le16toh(fl->sibling), ino, + "sibling"); + inf->rawloc = le32toh(fl->dataptr); + if (inf->rawloc >= 0x48000) { +invdptr: fprintf(stderr, + "error: inode %x data pointer is out of bounds\n", + ino); + exit(1); + } + inf->offset = inf->rawloc << 4; + if (inf->offset + inf->len > 0x480000) + goto invdptr; + inf->dataptr = image + inf->offset; + } + last_inode = ino - 1; + if (!last_inode) { + fprintf(stderr, "error: no inodes found!\n"); + exit(1); + } +} diff -r 86a494a5f2b0 -r 15c2ac2c5c73 pirollback/struct.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pirollback/struct.h Sat Jul 06 20:16:34 2013 +0000 @@ -0,0 +1,24 @@ +/* actual MPFFS on-media structure */ +struct inode_flash { + u16 len; + u8 reserved1; + u8 type; + u16 descend; + u16 sibling; + u32 dataptr; + u16 sequence; + u16 updates; +}; + +/* our own struct for convenience */ +struct inode_info { + struct inode_flash *flash; + int parent; + int type; + u8 *dataptr; + u32 offset; + u32 rawloc; + u16 len; + int descend; + int sibling; +}; diff -r 86a494a5f2b0 -r 15c2ac2c5c73 pirollback/types.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pirollback/types.h Sat Jul 06 20:16:34 2013 +0000 @@ -0,0 +1,12 @@ +/* + * I like using u8/u16/u32, but they don't seem to be defined anywhere. + * So I solve the whole portability problem by defining them myself. + */ + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; + +typedef signed char s8; +typedef signed short s16; +typedef signed int s32;