view mysteryffs/scan1.c @ 337:814d3f24bed6

frbl/README: minor updates
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 12 Mar 2020 20:46:33 +0000
parents d41c555d7f1d
children
line wrap: on
line source

/*
 * 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);
}