comparison mpffs/common.c @ 29:e96d6862cec0

mpffs-rdutils code started
author Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
date Sun, 30 Jun 2013 05:16:23 +0000
parents
children 9c3c5a572b57
comparison
equal deleted inserted replaced
28:c9f7a4afccc9 29:e96d6862cec0
1 /*
2 * This module contains the code that will be common between mpffs-cat,
3 * mpffs-ls and mpffs-xtr.
4 */
5
6 #include <sys/types.h>
7 #include <sys/file.h>
8 #include <sys/stat.h>
9 #include <endian.h>
10 #include <ctype.h>
11 #include <stdio.h>
12 #include <string.h>
13 #include <strings.h>
14 #include <stdlib.h>
15 #include <unistd.h>
16 #include "types.h"
17 #include "struct.h"
18
19 u8 mpffs_header[6] = {'F', 'f', 's', '#', 0x10, 0x02};
20
21 char *imgfile;
22 u32 eraseblk_size;
23 int total_blocks;
24 u32 total_ffs_size;
25 u8 *image, *indexblk;
26 int index_blk_num, root_node_no;
27 int verbose;
28
29 /*
30 * The following function is used to verify that the specified or computed
31 * flash erase block size is a power of 2.
32 */
33 count_ones(word)
34 u32 word;
35 {
36 int count;
37
38 for (count = 0; word; word >>= 1)
39 count += word & 1;
40 return count;
41 }
42
43 eraseblk_size_reasonable()
44 {
45 if (count_ones(eraseblk_size) != 1 || eraseblk_size < 16384) {
46 fprintf(stderr, "0x%lx is an unreasonable erase block size\n",
47 (u_long) eraseblk_size);
48 exit(1);
49 }
50 }
51
52 read_img_file()
53 {
54 int fd;
55 struct stat st;
56
57 fd = open(imgfile, O_RDONLY);
58 if (fd < 0) {
59 perror(imgfile);
60 exit(1);
61 }
62 fstat(fd, &st);
63 if (!S_ISREG(st.st_mode)) {
64 fprintf(stderr, "%s is not a regular file\n", imgfile);
65 exit(1);
66 }
67 if (!eraseblk_size && !total_blocks) {
68 switch (st.st_size) {
69 case 0x70000:
70 /* assume Closedmoko */
71 eraseblk_size = 0x10000;
72 total_blocks = 7;
73 break;
74 case 0x480000:
75 /* assume Pirelli */
76 eraseblk_size = 0x40000;
77 total_blocks = 18;
78 break;
79 default:
80 noauto: fprintf(stderr,
81 "cannot intuit the flash parameters of %s: use -e and -n options\n",
82 imgfile);
83 exit(1);
84 }
85 } else if (!total_blocks) {
86 total_blocks = st.st_size / eraseblk_size;
87 if (!total_blocks || total_blocks * eraseblk_size != st.st_size)
88 goto noauto;
89 } else if (!eraseblk_size) {
90 if (total_blocks * 0x10000 == st.st_size)
91 eraseblk_size = 0x10000;
92 else if (total_blocks * 0x40000 == st.st_size)
93 eraseblk_size = 0x40000;
94 else
95 goto noauto;
96 }
97 total_ffs_size = eraseblk_size * total_blocks;
98 if (st.st_size < total_ffs_size) {
99 fprintf(stderr, "%s has fewer than 0x%x bytes\n", imgfile,
100 total_ffs_size);
101 exit(1);
102 }
103 image = malloc(total_ffs_size);
104 if (!image) {
105 perror("malloc");
106 exit(1);
107 }
108 read(fd, image, total_ffs_size);
109 close(fd);
110 }
111
112 find_index_block()
113 {
114 int i, abcnt;
115 u8 *ptr;
116
117 if (index_blk_num) {
118 if (index_blk_num < 0 || index_blk_num >= total_blocks) {
119 fprintf(stderr,
120 "invalid block # given with the -a option\n");
121 exit(1);
122 }
123 ptr = image + index_blk_num * eraseblk_size;
124 if (bcmp(ptr, mpffs_header, 6) || ptr[8] != 0xAB) {
125 fprintf(stderr,
126 "no MPFFS index found at the specified block #%d\n",
127 index_blk_num);
128 exit(1);
129 }
130 indexblk = ptr;
131 return(0);
132 }
133 abcnt = 0;
134 for (ptr = image, i = 0; i < total_blocks; i++, ptr += eraseblk_size) {
135 if (bcmp(ptr, mpffs_header, 6)) {
136 fprintf(stderr,
137 "warning: no MPFFS signature in erase block #%d (offset %x)\n",
138 i, ptr - image);
139 continue;
140 }
141 switch (ptr[8]) {
142 case 0xAB:
143 if (verbose)
144 printf(
145 "Found AB index in erase block #%d (offset %x)\n",
146 i, ptr - image);
147 index_blk_num = i;
148 indexblk = ptr;
149 abcnt++;
150 continue;
151 case 0xBD:
152 case 0xBF:
153 continue;
154 }
155 fprintf(stderr,
156 "warning: non-understood block type %02X at offset %x\n",
157 ptr[8], ptr - image);
158 }
159 if (!indexblk) {
160 fprintf(stderr, "could not find an MPFFS index block in %s\n",
161 imgfile);
162 exit(1);
163 }
164 if (abcnt > 1) {
165 fprintf(stderr, "found more than one AB block; use -a\n");
166 exit(1);
167 }
168 return(0);
169 }
170
171 get_index_entry(oi)
172 struct objinfo *oi;
173 {
174 struct mpffs_index *le;
175
176 if (oi->entryno >= (eraseblk_size >> 4)) {
177 fprintf(stderr,
178 "error: index block pointer %x past the erase block size!\n",
179 oi->entryno);
180 exit(1);
181 }
182 le = (struct mpffs_index *) indexblk + oi->entryno;
183 oi->idxrec = le;
184 oi->len = le16toh(le->len);
185 oi->type = le->type;
186 oi->descend = le16toh(le->descend);
187 oi->sibling = le16toh(le->sibling);
188 return(0);
189 }
190
191 validate_chunk(oi)
192 struct objinfo *oi;
193 {
194 u32 dptr;
195
196 if (oi->len & 0xF || !oi->len) {
197 fprintf(stderr, "index entry #%x: invalid chunk length\n",
198 oi->entryno);
199 exit(1);
200 }
201 dptr = le32toh(oi->idxrec->dataptr);
202 if (dptr > 0x0FFFFFFF) {
203 invdptr: fprintf(stderr, "index entry #%x: invalid data pointer\n",
204 oi->entryno);
205 exit(1);
206 }
207 dptr <<= 4;
208 if (dptr >= total_img_size - oi->len)
209 goto invdptr;
210 oi->offset = dptr;
211 oi->dataptr = image + dptr;
212 return(0);
213 }
214
215 validate_obj_name(oi)
216 struct objinfo *oi;
217 {
218 u8 *cp;
219 int cnt;
220
221 for (cp = oi->dataptr, cnt = 0; ; cp++, cnt++) {
222 if (cnt >= oi->len) {
223 fprintf(stderr,
224 "object at index %x: name expected at %x: length overrun\n",
225 oi->entryno, oi->offset);
226 exit(1);
227 }
228 if (!*cp)
229 break;
230 if (*cp < '!' || *cp > '~') {
231 fprintf(stderr,
232 "object at index %x: name expected at %x: bad character\n",
233 oi->entryno, oi->offset);
234 exit(1);
235 }
236 }
237 if (!cnt) {
238 fprintf(stderr,
239 "object at index %x: name expected at %x: null string\n",
240 oi->entryno, oi->offset);
241 exit(1);
242 }
243 return(0);
244 }
245
246 u8 *
247 find_end_of_chunk(ch)
248 struct objinfo *ch;
249 {
250 u8 *p;
251 int i;
252
253 p = ch->dataptr + ch->len;
254 for (i = 1; i <= 16; i++) {
255 if (!p[-i])
256 return(p - i);
257 if (p[-1] != 0xFF)
258 break;
259 }
260 fprintf(stderr,
261 "chunk starting at %x (index entry %x): no valid termination found\n",
262 ch->offset, ch->entryno);
263 exit(1);
264 }