FreeCalypso > hg > freecalypso-reveng
diff pirollback/journal.c @ 46:78ac405716db
pirollback: journal parsing implemented
author | Michael Spacefalcon <msokolov@ivan.Harhan.ORG> |
---|---|
date | Sun, 07 Jul 2013 06:14:40 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pirollback/journal.c Sun Jul 07 06:14:40 2013 +0000 @@ -0,0 +1,143 @@ +#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); + } +}