FreeCalypso > hg > freecalypso-reveng
comparison mysteryffs/scan1.c @ 21:d41c555d7f1d
beginning to explore MysteryFFS
author | Michael Spacefalcon <msokolov@ivan.Harhan.ORG> |
---|---|
date | Sat, 18 May 2013 08:22:15 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
20:a52e76c12e6b | 21:d41c555d7f1d |
---|---|
1 /* | |
2 * This program is the first MysteryFFS analysis tool written. | |
3 * Here I'm trying to understand the meaning of various fields | |
4 * in the index block records. | |
5 */ | |
6 | |
7 #include <sys/types.h> | |
8 #include <sys/file.h> | |
9 #include <sys/stat.h> | |
10 #include <endian.h> | |
11 #include <ctype.h> | |
12 #include <stdio.h> | |
13 #include <string.h> | |
14 #include <strings.h> | |
15 #include <stdlib.h> | |
16 #include <unistd.h> | |
17 | |
18 typedef unsigned char u8; | |
19 typedef unsigned short u16; | |
20 typedef unsigned int u32; | |
21 | |
22 u8 blank_line[16] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | |
23 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; | |
24 | |
25 u8 mysteryffs_hdr[6] = {'F', 'f', 's', '#', 0x10, 0x02}; | |
26 | |
27 struct index_entry { | |
28 u16 len; | |
29 u8 unknown1; | |
30 u8 type; | |
31 u16 nptr1; | |
32 u16 nptr2; | |
33 u32 dataptr; | |
34 u16 unknown2; | |
35 u16 version; | |
36 }; | |
37 | |
38 char *imgfile; | |
39 u32 eraseblk_size; | |
40 int total_blocks; | |
41 u32 total_img_size; | |
42 u8 *image, *indexblk; | |
43 | |
44 read_img_file() | |
45 { | |
46 int fd; | |
47 struct stat st; | |
48 | |
49 fd = open(imgfile, O_RDONLY); | |
50 if (fd < 0) { | |
51 perror(imgfile); | |
52 exit(1); | |
53 } | |
54 fstat(fd, &st); | |
55 if (!S_ISREG(st.st_mode)) { | |
56 fprintf(stderr, "%s is not a regular file\n", imgfile); | |
57 exit(1); | |
58 } | |
59 if (st.st_size < total_img_size) { | |
60 fprintf(stderr, "%s has fewer than 0x%x bytes\n", imgfile, | |
61 total_img_size); | |
62 exit(1); | |
63 } | |
64 image = malloc(total_img_size); | |
65 if (!image) { | |
66 perror("malloc"); | |
67 exit(1); | |
68 } | |
69 read(fd, image, total_img_size); | |
70 close(fd); | |
71 } | |
72 | |
73 find_index_block() | |
74 { | |
75 int i; | |
76 u8 *ptr; | |
77 | |
78 for (ptr = image, i = 0; i < total_blocks; i++, ptr += eraseblk_size) { | |
79 if (bcmp(ptr, mysteryffs_hdr, 6)) | |
80 continue; | |
81 if (ptr[8] != 0xAB) | |
82 continue; | |
83 indexblk = ptr; | |
84 return(0); | |
85 } | |
86 fprintf(stderr, "could not find a MysteryFFS index block in %s\n", | |
87 imgfile); | |
88 exit(1); | |
89 } | |
90 | |
91 is_namestr_ok(s) | |
92 char *s; | |
93 { | |
94 int cnt; | |
95 | |
96 for (cnt = 0; *s; s++, cnt++) { | |
97 if (cnt >= 32) | |
98 return(0); | |
99 if (!isprint(*s)) | |
100 return(0); | |
101 } | |
102 if (cnt) | |
103 return(1); | |
104 else | |
105 return(0); | |
106 } | |
107 | |
108 char * | |
109 dataptr_to_name(dptr) | |
110 u32 dptr; | |
111 { | |
112 u8 *data; | |
113 | |
114 if (dptr > 0x0FFFFFFF) { | |
115 inv: return("<invptr>"); | |
116 } | |
117 dptr <<= 4; | |
118 if (dptr >= total_img_size) | |
119 goto inv; | |
120 data = image + dptr; | |
121 if (is_namestr_ok(data)) | |
122 return(data); | |
123 else | |
124 return("<notname>"); | |
125 } | |
126 | |
127 dump_entry(rawptr, entrynum) | |
128 u8 *rawptr; | |
129 { | |
130 struct index_entry ent; | |
131 | |
132 bcopy(rawptr, &ent, 0x10); | |
133 ent.len = le16toh(ent.len); | |
134 ent.nptr1 = le16toh(ent.nptr1); | |
135 ent.nptr2 = le16toh(ent.nptr2); | |
136 ent.dataptr = le32toh(ent.dataptr); | |
137 ent.unknown2 = le16toh(ent.unknown2); | |
138 ent.version = le16toh(ent.version); | |
139 printf("%x %s: len=%x %02X %02X nptr1=%x nptr2=%x %04X %04X\n", | |
140 entrynum, dataptr_to_name(ent.dataptr), | |
141 ent.len, ent.unknown1, ent.type, | |
142 ent.nptr1, ent.nptr2, | |
143 ent.unknown2, ent.version); | |
144 } | |
145 | |
146 dump_index() | |
147 { | |
148 u32 offset; | |
149 u8 *entry; | |
150 | |
151 for (offset = 0x10; offset < eraseblk_size; offset += 0x10) { | |
152 entry = indexblk + offset; | |
153 if (!bcmp(entry, blank_line, 16)) | |
154 continue; | |
155 dump_entry(entry, offset >> 4); | |
156 } | |
157 } | |
158 | |
159 main(argc, argv) | |
160 char **argv; | |
161 { | |
162 if (argc != 4) { | |
163 fprintf(stderr, "usage: %s imgfile blksize nblocks\n", argv[0]); | |
164 exit(1); | |
165 } | |
166 imgfile = argv[1]; | |
167 eraseblk_size = strtoul(argv[2], 0, 0); | |
168 total_blocks = strtoul(argv[3], 0, 0); | |
169 total_img_size = eraseblk_size * total_blocks; | |
170 read_img_file(); | |
171 find_index_block(); | |
172 dump_index(); | |
173 exit(0); | |
174 } |