diff mysteryffs/scan1.c @ 21:d41c555d7f1d

beginning to explore MysteryFFS
author Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
date Sat, 18 May 2013 08:22:15 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mysteryffs/scan1.c	Sat May 18 08:22:15 2013 +0000
@@ -0,0 +1,174 @@
+/*
+ * This program is the first MysteryFFS analysis tool written.
+ * Here I'm trying to understand the meaning of various fields
+ * in the index block records.
+ */
+
+#include <sys/types.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <endian.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef unsigned int u32;
+
+u8 blank_line[16] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+		     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
+
+u8 mysteryffs_hdr[6] = {'F', 'f', 's', '#', 0x10, 0x02};
+
+struct index_entry {
+	u16	len;
+	u8	unknown1;
+	u8	type;
+	u16	nptr1;
+	u16	nptr2;
+	u32	dataptr;
+	u16	unknown2;
+	u16	version;
+};
+
+char *imgfile;
+u32 eraseblk_size;
+int total_blocks;
+u32 total_img_size;
+u8 *image, *indexblk;
+
+read_img_file()
+{
+	int fd;
+	struct stat st;
+
+	fd = open(imgfile, O_RDONLY);
+	if (fd < 0) {
+		perror(imgfile);
+		exit(1);
+	}
+	fstat(fd, &st);
+	if (!S_ISREG(st.st_mode)) {
+		fprintf(stderr, "%s is not a regular file\n", imgfile);
+		exit(1);
+	}
+	if (st.st_size < total_img_size) {
+		fprintf(stderr, "%s has fewer than 0x%x bytes\n", imgfile,
+			total_img_size);
+		exit(1);
+	}
+	image = malloc(total_img_size);
+	if (!image) {
+		perror("malloc");
+		exit(1);
+	}
+	read(fd, image, total_img_size);
+	close(fd);
+}
+
+find_index_block()
+{
+	int i;
+	u8 *ptr;
+
+	for (ptr = image, i = 0; i < total_blocks; i++, ptr += eraseblk_size) {
+		if (bcmp(ptr, mysteryffs_hdr, 6))
+			continue;
+		if (ptr[8] != 0xAB)
+			continue;
+		indexblk = ptr;
+		return(0);
+	}
+	fprintf(stderr, "could not find a MysteryFFS index block in %s\n",
+		imgfile);
+	exit(1);
+}
+
+is_namestr_ok(s)
+	char *s;
+{
+	int cnt;
+
+	for (cnt = 0; *s; s++, cnt++) {
+		if (cnt >= 32)
+			return(0);
+		if (!isprint(*s))
+			return(0);
+	}
+	if (cnt)
+		return(1);
+	else
+		return(0);
+}
+
+char *
+dataptr_to_name(dptr)
+	u32 dptr;
+{
+	u8 *data;
+
+	if (dptr > 0x0FFFFFFF) {
+inv:		return("<invptr>");
+	}
+	dptr <<= 4;
+	if (dptr >= total_img_size)
+		goto inv;
+	data = image + dptr;
+	if (is_namestr_ok(data))
+		return(data);
+	else
+		return("<notname>");
+}
+
+dump_entry(rawptr, entrynum)
+	u8 *rawptr;
+{
+	struct index_entry ent;
+
+	bcopy(rawptr, &ent, 0x10);
+	ent.len = le16toh(ent.len);
+	ent.nptr1 = le16toh(ent.nptr1);
+	ent.nptr2 = le16toh(ent.nptr2);
+	ent.dataptr = le32toh(ent.dataptr);
+	ent.unknown2 = le16toh(ent.unknown2);
+	ent.version = le16toh(ent.version);
+	printf("%x %s: len=%x %02X %02X nptr1=%x nptr2=%x %04X %04X\n",
+		entrynum, dataptr_to_name(ent.dataptr),
+		ent.len, ent.unknown1, ent.type,
+		ent.nptr1, ent.nptr2,
+		ent.unknown2, ent.version);
+}
+
+dump_index()
+{
+	u32 offset;
+	u8 *entry;
+
+	for (offset = 0x10; offset < eraseblk_size; offset += 0x10) {
+		entry = indexblk + offset;
+		if (!bcmp(entry, blank_line, 16))
+			continue;
+		dump_entry(entry, offset >> 4);
+	}
+}
+
+main(argc, argv)
+	char **argv;
+{
+	if (argc != 4) {
+		fprintf(stderr, "usage: %s imgfile blksize nblocks\n", argv[0]);
+		exit(1);
+	}
+	imgfile = argv[1];
+	eraseblk_size = strtoul(argv[2], 0, 0);
+	total_blocks = strtoul(argv[3], 0, 0);
+	total_img_size = eraseblk_size * total_blocks;
+	read_img_file();
+	find_index_block();
+	dump_index();
+	exit(0);
+}