annotate pirollback/init.c @ 103:a10acb1688e0

thumbdis: buglet in the decoding of sub-from-sp
author Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
date Mon, 31 Mar 2014 01:59:28 +0000
parents 15c2ac2c5c73
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
42
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
1 #include <sys/types.h>
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
2 #include <sys/file.h>
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
3 #include <endian.h>
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
4 #include <stdio.h>
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
5 #include <string.h>
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
6 #include <strings.h>
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
7 #include <stdlib.h>
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
8 #include <unistd.h>
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
9 #include "types.h"
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
10 #include "struct.h"
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
11
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
12 u8 blank_flash_line[16] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
13 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
14
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
15 char *imgfile;
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
16 u8 image[0x480000];
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
17 struct inode_info inode[0x4000];
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
18 int last_inode;
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
19
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
20 static u8 magichdr_first[9] = {'F','f','s','#', 0x10, 0x02, 0xFF, 0xFF, 0xAB};
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
21 static u8 magichdr_mid[9] = {'F','f','s','#', 0x10, 0x02, 0xFF, 0xFF, 0xBD};
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
22 static u8 magichdr_last[9] = {'F','f','s','#', 0x10, 0x02, 0xFF, 0xFF, 0xBF};
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
23
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
24 read_img_file()
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
25 {
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
26 int i, fd, cc;
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
27 u8 *blk, *compare;
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
28
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
29 fd = open(imgfile, O_RDONLY);
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
30 if (fd < 0) {
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
31 perror(imgfile);
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
32 exit(1);
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
33 }
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
34 cc = read(fd, image, sizeof image);
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
35 close(fd);
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
36 if (cc != sizeof image) {
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
37 inv: fprintf(stderr,
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
38 "%s does not appear to be a \"virgin\" Pirelli FFS image\n",
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
39 imgfile);
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
40 exit(1);
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
41 }
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
42 for (i = 0; i < 18; i++) {
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
43 blk = image + i * 0x40000;
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
44 if (i == 0)
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
45 compare = magichdr_first;
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
46 else if (i == 17)
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
47 compare = magichdr_last;
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
48 else
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
49 compare = magichdr_mid;
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
50 if (bcmp(blk, compare, 9))
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
51 goto inv;
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
52 }
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
53 }
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
54
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
55 static int
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
56 convert_ptr(ptr, ino, which)
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
57 int ptr, ino;
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
58 char *which;
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
59 {
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
60 if (ptr >= 1 && ptr <= 0x3FFF)
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
61 return(ptr);
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
62 if (ptr == 0xFFFF)
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
63 return(0);
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
64 fprintf(stderr, "error in inode #%x: invalid %s pointer\n", ino, which);
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
65 exit(1);
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
66 }
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
67
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
68 read_inodes()
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
69 {
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
70 int ino;
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
71 struct inode_flash *fl;
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
72 struct inode_info *inf;
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
73
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
74 for (ino = 1; ino < 0x4000; ino++) {
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
75 fl = (struct inode_flash *) image + ino;
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
76 if (!bcmp(fl, blank_flash_line, 16))
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
77 break;
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
78 inf = inode + ino;
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
79 inf->flash = fl;
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
80 inf->len = le16toh(fl->len);
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
81 if (!inf->len) {
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
82 fprintf(stderr, "error: inode %x has zero length\n",
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
83 ino);
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
84 exit(1);
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
85 }
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
86 if (inf->len & 0xF) {
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
87 fprintf(stderr, "error: inode %x has bad length\n",
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
88 ino);
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
89 exit(1);
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
90 }
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
91 inf->type = fl->type;
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
92 inf->descend = convert_ptr(le16toh(fl->descend), ino,
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
93 "descendant");
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
94 inf->sibling = convert_ptr(le16toh(fl->sibling), ino,
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
95 "sibling");
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
96 inf->rawloc = le32toh(fl->dataptr);
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
97 if (inf->rawloc >= 0x48000) {
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
98 invdptr: fprintf(stderr,
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
99 "error: inode %x data pointer is out of bounds\n",
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
100 ino);
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
101 exit(1);
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
102 }
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
103 inf->offset = inf->rawloc << 4;
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
104 if (inf->offset + inf->len > 0x480000)
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
105 goto invdptr;
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
106 inf->dataptr = image + inf->offset;
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
107 }
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
108 last_inode = ino - 1;
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
109 if (!last_inode) {
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
110 fprintf(stderr, "error: no inodes found!\n");
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
111 exit(1);
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
112 }
15c2ac2c5c73 pirollback: started
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
113 }