view pirollback/journal.c @ 371:c7514c8b5b41

pirelli/headset: plug insertion detection figured out
author Mychaela Falconia <falcon@freecalypso.org>
date Mon, 14 Jun 2021 01:33:48 +0000
parents 78ac405716db
children
line wrap: on
line source

#include <sys/types.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"

extern u8 image[0x480000];
extern struct inode_info inode[];
extern int last_inode;
extern u8 blank_flash_line[16];

int journal_start_ino;

find_journal()
{
	int ino;
	struct inode_info *inf;

	for (ino = 2; ino <= last_inode; ino++) {
		inf = inode + ino;
		if (inf->type == 0xE1 && inf->parent == 1 &&
		    !strcmp(inf->dataptr, ".journal"))
			return(ino);
	}
	fprintf(stderr, "error: cannot find /.journal\n");
	exit(1);
}

parse_journal()
{
	struct inode_info *inf;
	struct journal_entry *jr, *endp;
	int ino = 0;
	u16 tempu16;
	s16 temps16;

	inf = inode + find_journal();
	if (inf->len != 0x4010) {
		fprintf(stderr,
			"error: /.journal file length differs from expected\n");
		exit(1);
	}
	jr = (struct journal_entry *)(inf->dataptr + 0xC);
	for (endp = jr + 0x3FF; jr < endp; jr++) {
		if (!bcmp(jr, blank_flash_line, 16))
			break;
		if (jr->status != 0xF1) {
			fprintf(stderr,
				"journal record at %x: status byte != F1\n",
				(u8 *) jr - image);
			exit(1);
		}
		tempu16 = le16toh(jr->this_ino);
		if (ino) {
			ino++;
			if (ino != tempu16) {
				fprintf(stderr,
			"journal record at %x: break in inode # sequence\n",
					(u8 *) jr - image);
				exit(1);
			}
		} else {
			ino = tempu16;
			journal_start_ino = ino;
		}
		if (ino < 3 || ino > last_inode) {
			fprintf(stderr,
				"journal record at %x: inode # out of range\n",
				(u8 *) jr - image);
			exit(1);
		}
		inf = inode + ino;
		inf->jflash = jr;
		if (inf->type) {
			if (jr->objtype != inf->type) {
				fprintf(stderr,
					"journal record at %x: type mismatch\n",
					(u8 *) jr - image);
				exit(1);
			}
		} else {
			switch (jr->objtype) {
			case 0xE1:
			case 0xF1:
			case 0xF2:
			case 0xF4:
				break;
			default:
				fprintf(stderr,
			"journal record at %x: unexpected type byte value\n",
					(u8 *) jr - image);
				exit(1);
			}
			inf->type = jr->objtype;
		}
		if (le32toh(jr->location) != inf->rawloc) {
			fprintf(stderr,
			"journal record at %x: location field mismatch\n",
				(u8 *) jr - image);
			exit(1);
		}
		if (le16toh(jr->size) != inf->len) {
			fprintf(stderr,
				"journal record at %x: size field mismatch\n",
				(u8 *) jr - image);
			exit(1);
		}
		temps16 = le16toh(jr->link_ptr);
		if (temps16 < -last_inode || temps16 > last_inode) {
			fprintf(stderr,
			"journal record at %x: linkptr field out of range\n",
				(u8 *) jr - image);
			exit(1);
		}
		inf->j_unlink_ptr = temps16;
		temps16 = le16toh(jr->replacee);
		if (temps16 < 0 || temps16 > last_inode) {
			fprintf(stderr,
			"journal record at %x: replacee field out of range\n",
				(u8 *) jr - image);
			exit(1);
		}
		inf->j_oldver = temps16;
		if (jr->repli) {
			fprintf(stderr,
	"journal record at %x: last 16-bit word is not zero as expected\n",
				(u8 *) jr - image);
			exit(1);
		}
	}
	if (!ino) {
		fprintf(stderr, "error: journal is empty!\n");
		exit(1);
	}
	if (ino != last_inode) {
		fprintf(stderr, "error: journal end != inode block end\n");
		exit(1);
	}
}