view pirollback/init.c @ 406:1a852266ba74 default tip

tfo moved to gsm-net-reveng repository
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 24 May 2024 21:19:59 +0000
parents 15c2ac2c5c73
children
line wrap: on
line source

#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);
	}
}