FreeCalypso > hg > freecalypso-reveng
view pirollback/rollback.c @ 106:a39a38bbec4d
analysis of what osmocon's voodoo payloads disassemble to in ARM/Thumb
author | Michael Spacefalcon <msokolov@ivan.Harhan.ORG> |
---|---|
date | Mon, 31 Mar 2014 06:33:14 +0000 |
parents | e516128db432 |
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" #include "pathname.h" extern char *imgfile; extern u8 image[0x480000]; extern struct inode_info inode[]; extern int last_inode; extern int journal_start_ino; static void report_inode(ino) { struct inode_info *inf = inode + ino; char pathname[PATHNAME_BUF_SIZE]; int typechar; switch (inf->type) { case 0xF1: typechar = 'f'; break; case 0xF2: typechar = 'd'; break; case 0xF4: typechar = '.'; break; default: fprintf(stderr, "inode #%x: unexpected type %02X\n", ino, inf->type); exit(1); } if (pathname_of_inode(ino, pathname) < 0) strcpy(pathname, "-nopath-"); printf("reverting #%04X %c %s\n", ino, typechar, pathname); } static void unlink_inode(oldino, newino, is_sibling) { struct inode_info *inf = inode + oldino; struct inode_flash *fl = inf->flash; u16 *flashp; if (is_sibling) flashp = &fl->sibling; else flashp = &fl->descend; if (le16toh(*flashp) != newino) { fprintf(stderr, "fail: %s pointer of inode #%x does not point to #%x as expected\n", is_sibling ? "sibling" : "descend", oldino, newino); exit(1); } /* unprogram it! */ *flashp = 0xFFFF; } static void resurrect_descend_chain(headino, ino) { struct inode_info *inf; u8 *typebyte; for (; ino; ino = inf->descend) { inf = inode + ino; if (inf->type != 0xF4) { fprintf(stderr, "error: #%x, descendant of #%x, is not of type F4\n", ino, headino); exit(1); } typebyte = &inf->flash->type; if (*typebyte) { fprintf(stderr, "inode #%x to be resurrected: not in deleted state\n", ino); exit(1); } /* undo the zeroing */ *typebyte = 0xF4; } } static void resurrect_old_ver(oldino, newino) { struct inode_info *old = inode + oldino; struct inode_info *new = inode + newino; u8 *typebyte; if (old->type != new->type || old->parent != new->parent || strcmp(old->dataptr, new->dataptr)) { fprintf(stderr, "inode #%x replacing #%x: mismatch error\n", newino, oldino); exit(1); } /* the item of interest is the old in-flash type byte */ typebyte = &old->flash->type; if (*typebyte) { fprintf(stderr, "inode #%x to be resurrected: not in deleted state\n", oldino); exit(1); } /* undo the zeroing */ *typebyte = old->type; /* * Is there a descendant chain (file continuation chunks) * to resurrect as well? */ if (!old->descend) return; if (old->type != 0xF1) { fprintf(stderr, "resurrecting inode #%x: unexpected descendant with type != F1\n", oldino); exit(1); } resurrect_descend_chain(oldino, old->descend); } roll_back_inode(ino) { struct inode_info *inf = inode + ino; report_inode(ino); if (!inf->flash->type) printf("NOTE: object is already in deleted state\n"); /* first order of business: unlink it */ if (inf->j_unlink_ptr < 0) unlink_inode(-inf->j_unlink_ptr, ino, 0); else unlink_inode(inf->j_unlink_ptr, ino, 1); /* resurrect the previous version */ if (inf->type != 0xF4) { if (inf->j_oldver) resurrect_old_ver(inf->j_oldver, ino); else printf("NOTE: no previous version to resurrect\n"); } else if (inf->j_oldver) { fprintf(stderr, "error: unexpected oldver on inode #%x of type F4\n", ino); exit(1); } /* reblank the 3 flash areas programmed with this inode */ memset(inf->flash, 0xFF, 16); memset(inf->jflash, 0xFF, 16); memset(inf->dataptr, 0xFF, inf->len); } write_new_img(outfilename) char *outfilename; { int fd, cc; fd = open(outfilename, O_WRONLY|O_CREAT|O_TRUNC, 0666); if (fd < 0) { perror(outfilename); exit(1); } cc = write(fd, image, sizeof image); close(fd); if (cc != sizeof image) { fprintf(stderr, "error writing to %s\n", outfilename); exit(1); } } main(argc, argv) char **argv; { int ino, keep_ino; char *strtoul_endp; if (argc != 4) { usage: fprintf(stderr, "usage: %s ffs-image inode-to-keep new-image\n", argv[0]); exit(1); } imgfile = argv[1]; keep_ino = strtoul(argv[2], &strtoul_endp, 16); if (!argv[2][0] || *strtoul_endp) goto usage; read_img_file(); read_inodes(); walk_tree(); check_object_names(); parse_journal(); check_object_names(); /* rerun for "undeleted" objects */ if (keep_ino < journal_start_ino || keep_ino > last_inode) { fprintf(stderr, "%s: bad inode number specified\n", argv[0]); exit(1); } for (ino = last_inode; ino > keep_ino; ino--) roll_back_inode(ino); write_new_img(argv[3]); exit(0); }