changeset 42:15c2ac2c5c73

pirollback: started
author Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
date Sat, 06 Jul 2013 20:16:34 +0000
parents 86a494a5f2b0
children 9f4469766c74
files .hgignore pirollback/Makefile pirollback/README pirollback/analyze.c pirollback/init.c pirollback/struct.h pirollback/types.h
diffstat 7 files changed, 193 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- 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$
--- /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}
--- /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.
--- /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 <stdio.h>
+#include <stdlib.h>
+
+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);
+}
--- /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 <sys/types.h>
+#include <sys/file.h>
+#include <endian.h>
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+#include <stdlib.h>
+#include <unistd.h>
+#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);
+	}
+}
--- /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;
+};
--- /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;