diff options
author | Maurus Cuelenaere <mcuelenaere@gmail.com> | 2008-07-11 15:50:46 +0000 |
---|---|---|
committer | Maurus Cuelenaere <mcuelenaere@gmail.com> | 2008-07-11 15:50:46 +0000 |
commit | 14c7f45cdae826f88dc539c8c38dd95caf305731 (patch) | |
tree | 832da054b7cfb2dc6fd63339af736625f31d21aa /utils/zenutils/source/shared | |
parent | 7c84ede3781c27db73403bd6302f320c76a58c8c (diff) | |
download | rockbox-14c7f45cdae826f88dc539c8c38dd95caf305731.tar.gz rockbox-14c7f45cdae826f88dc539c8c38dd95caf305731.zip |
Add zook's ZenUtils to SVN
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@18010 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'utils/zenutils/source/shared')
-rwxr-xr-x | utils/zenutils/source/shared/CMakeLists.txt | 16 | ||||
-rwxr-xr-x | utils/zenutils/source/shared/cenc.cpp | 333 | ||||
-rwxr-xr-x | utils/zenutils/source/shared/cenc.h | 29 | ||||
-rwxr-xr-x | utils/zenutils/source/shared/crypt.cpp | 91 | ||||
-rwxr-xr-x | utils/zenutils/source/shared/crypt.h | 30 | ||||
-rwxr-xr-x | utils/zenutils/source/shared/file.cpp | 106 | ||||
-rwxr-xr-x | utils/zenutils/source/shared/file.h | 36 | ||||
-rwxr-xr-x | utils/zenutils/source/shared/firmware.cpp | 387 | ||||
-rwxr-xr-x | utils/zenutils/source/shared/firmware.h | 92 | ||||
-rwxr-xr-x | utils/zenutils/source/shared/pe.cpp | 128 | ||||
-rwxr-xr-x | utils/zenutils/source/shared/pe.h | 142 | ||||
-rwxr-xr-x | utils/zenutils/source/shared/shared.cpp | 0 | ||||
-rwxr-xr-x | utils/zenutils/source/shared/updater.cpp | 151 | ||||
-rwxr-xr-x | utils/zenutils/source/shared/updater.h | 32 | ||||
-rwxr-xr-x | utils/zenutils/source/shared/utils.cpp | 211 | ||||
-rwxr-xr-x | utils/zenutils/source/shared/utils.h | 68 |
16 files changed, 1852 insertions, 0 deletions
diff --git a/utils/zenutils/source/shared/CMakeLists.txt b/utils/zenutils/source/shared/CMakeLists.txt new file mode 100755 index 0000000000..2e42dbbe74 --- /dev/null +++ b/utils/zenutils/source/shared/CMakeLists.txt | |||
@@ -0,0 +1,16 @@ | |||
1 | PROJECT(shared) | ||
2 | |||
3 | # source files for shared | ||
4 | SET(shared_srcs | ||
5 | cenc.cpp | ||
6 | crypt.cpp | ||
7 | file.cpp | ||
8 | firmware.cpp | ||
9 | pe.cpp | ||
10 | updater.cpp | ||
11 | utils.cpp | ||
12 | ) | ||
13 | |||
14 | ADD_LIBRARY(shared ${shared_srcs}) | ||
15 | TARGET_LINK_LIBRARIES(shared pelib) | ||
16 | TARGET_LINK_LIBRARIES(shared zlib) | ||
diff --git a/utils/zenutils/source/shared/cenc.cpp b/utils/zenutils/source/shared/cenc.cpp new file mode 100755 index 0000000000..932bee4625 --- /dev/null +++ b/utils/zenutils/source/shared/cenc.cpp | |||
@@ -0,0 +1,333 @@ | |||
1 | /* zenutils - Utilities for working with creative firmwares. | ||
2 | * Copyright 2007 (c) Rasmus Ry <rasmus.ry{at}gmail.com> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
17 | */ | ||
18 | |||
19 | #include "cenc.h" | ||
20 | #include <firmware.h> | ||
21 | #include <stdexcept> | ||
22 | |||
23 | |||
24 | namespace { | ||
25 | const byte CODE_MASK = 0xC0; | ||
26 | const byte ARGS_MASK = 0x3F; | ||
27 | |||
28 | const byte REPEAT_CODE = 0x00; | ||
29 | const byte BLOCK_CODE = 0x40; | ||
30 | const byte LONG_RUN_CODE = 0x80; | ||
31 | const byte SHORT_RUN_CODE = 0xC0; | ||
32 | |||
33 | const byte BLOCK_ARGS = 0x1F; | ||
34 | const byte BLOCK_MODE = 0x20; | ||
35 | |||
36 | |||
37 | void decode_run(byte* dst, word len, byte val, | ||
38 | int& dstidx) | ||
39 | { | ||
40 | memset(dst + dstidx, val, len); | ||
41 | dstidx += len; | ||
42 | } | ||
43 | |||
44 | void decode_pattern(byte* src, byte* dst, | ||
45 | word len, int& srcidx, int& dstidx, | ||
46 | bool bdecode, int npasses) | ||
47 | { | ||
48 | for (int i = 0; i < npasses; i++) | ||
49 | { | ||
50 | if (bdecode) | ||
51 | { | ||
52 | for (int j = 0; j < len; j++) | ||
53 | { | ||
54 | word c, d; | ||
55 | c = src[srcidx + j]; | ||
56 | d = (c >> 5) & 7; | ||
57 | c = (c << 3) & 0xF8; | ||
58 | src[srcidx + j] = static_cast<byte>(c | d); | ||
59 | } | ||
60 | bdecode = false; | ||
61 | } | ||
62 | memcpy(dst + dstidx, src + srcidx, len); | ||
63 | dstidx += len; | ||
64 | } | ||
65 | srcidx += len; | ||
66 | } | ||
67 | }; //namespace | ||
68 | |||
69 | int zen::cenc_decode(byte* src, int srclen, byte* dst, int dstlen) | ||
70 | { | ||
71 | if (!src || !srclen || !dst || !dstlen) | ||
72 | { | ||
73 | throw std::invalid_argument("Invalid argument(s)."); | ||
74 | } | ||
75 | |||
76 | int i = 0, j = 0; | ||
77 | do | ||
78 | { | ||
79 | word c, d, e; | ||
80 | c = src[i++]; | ||
81 | switch (c & CODE_MASK) | ||
82 | { | ||
83 | case REPEAT_CODE: // 2 bytes | ||
84 | d = src[i++]; | ||
85 | d = d + 2; | ||
86 | |||
87 | e = (c & ARGS_MASK) + 2; | ||
88 | |||
89 | decode_pattern(src, dst, e, i, j, false, d); | ||
90 | break; | ||
91 | |||
92 | case BLOCK_CODE: // 1/2/3 bytes | ||
93 | d = c & BLOCK_ARGS; | ||
94 | if (!(c & BLOCK_MODE)) | ||
95 | { | ||
96 | e = src[i++]; | ||
97 | e = (d << 8) + (e + 0x21); | ||
98 | |||
99 | d = static_cast<word>(i ^ j); | ||
100 | } | ||
101 | else | ||
102 | { | ||
103 | e = d + 1; | ||
104 | |||
105 | d = static_cast<word>(i ^ j); | ||
106 | } | ||
107 | if (d & 1) | ||
108 | { | ||
109 | i++; | ||
110 | } | ||
111 | |||
112 | decode_pattern(src, dst, e, i, j, true, 1); | ||
113 | break; | ||
114 | |||
115 | case LONG_RUN_CODE: // 3 bytes | ||
116 | d = src[i++]; | ||
117 | e = ((c & ARGS_MASK) << 8) + (d + 0x42); | ||
118 | |||
119 | d = src[i++]; | ||
120 | d = ((d & 7) << 5) | ((d >> 3) & 0x1F); | ||
121 | |||
122 | decode_run(dst, e, static_cast<byte>(d), j); | ||
123 | break; | ||
124 | |||
125 | case SHORT_RUN_CODE: // 2 bytes | ||
126 | d = src[i++]; | ||
127 | d = ((d & 3) << 6) | ((d >> 2) & 0x3F); | ||
128 | |||
129 | e = (c & ARGS_MASK) + 2; | ||
130 | |||
131 | decode_run(dst, e, static_cast<byte>(d), j); | ||
132 | break; | ||
133 | }; | ||
134 | } while (i < srclen && j < dstlen); | ||
135 | |||
136 | return j; | ||
137 | } | ||
138 | |||
139 | namespace { | ||
140 | int encode_run(byte* dst, int& dstidx, byte val, int len, int dstlen) | ||
141 | { | ||
142 | if (len < 2) | ||
143 | throw std::invalid_argument("Length is too small."); | ||
144 | |||
145 | int ret = 0; | ||
146 | if (len <= 0x41) | ||
147 | { | ||
148 | if ((dstidx + 2) > dstlen) | ||
149 | throw std::runtime_error("Not enough space to store run."); | ||
150 | |||
151 | dst[dstidx++] = SHORT_RUN_CODE | (((len - 2) & ARGS_MASK)); | ||
152 | dst[dstidx++] = ((val >> 6) & 3) | ((val & 0x3F) << 2); | ||
153 | |||
154 | ret = 2; | ||
155 | } | ||
156 | else if (len <= 0x4041) | ||
157 | { | ||
158 | if ((dstidx + 3) > dstlen) | ||
159 | throw std::runtime_error("Not enough space to store run."); | ||
160 | |||
161 | byte b1 = (len - 0x42) >> 8; | ||
162 | byte b2 = (len - 0x42) & 0xFF; | ||
163 | |||
164 | dst[dstidx++] = LONG_RUN_CODE | ((b1 & ARGS_MASK)); | ||
165 | dst[dstidx++] = b2; | ||
166 | dst[dstidx++] = ((val >> 5) & 7) | ((val & 0x1F) << 3); | ||
167 | |||
168 | ret = 3; | ||
169 | } | ||
170 | else | ||
171 | { | ||
172 | int long_count = len / 0x4041; | ||
173 | int short_len = len % 0x4041; | ||
174 | bool toosmall = short_len == 1; | ||
175 | |||
176 | int run_len = 0x4041; | ||
177 | for (int i = 0; i < long_count; i++) | ||
178 | { | ||
179 | if (toosmall && (i == (long_count-1))) | ||
180 | { | ||
181 | run_len--; | ||
182 | toosmall = false; | ||
183 | } | ||
184 | int tmp = encode_run(dst, dstidx, val, run_len, dstlen); | ||
185 | if (!tmp) return 0; | ||
186 | ret += tmp; | ||
187 | len -= run_len; | ||
188 | } | ||
189 | |||
190 | if (len) | ||
191 | { | ||
192 | int short_count = len / 0x41; | ||
193 | int short_rest = short_count ? (len % 0x41) : 0; | ||
194 | toosmall = short_rest == 1; | ||
195 | |||
196 | run_len = 0x41; | ||
197 | for (int i = 0; i < short_count; i++) | ||
198 | { | ||
199 | if (toosmall && (i == (short_count-1))) | ||
200 | { | ||
201 | run_len--; | ||
202 | toosmall = false; | ||
203 | } | ||
204 | int tmp = encode_run(dst, dstidx, val, run_len, dstlen); | ||
205 | if (!tmp) return 0; | ||
206 | ret += tmp; | ||
207 | len -= run_len; | ||
208 | } | ||
209 | int tmp = encode_run(dst, dstidx, val, len, dstlen); | ||
210 | if (!tmp) return 0; | ||
211 | ret += tmp; | ||
212 | len -= len; | ||
213 | } | ||
214 | } | ||
215 | |||
216 | return ret; | ||
217 | } | ||
218 | |||
219 | int encode_block(byte* dst, int& dstidx, byte* src, int& srcidx, int len, | ||
220 | int dstlen) | ||
221 | { | ||
222 | if (len < 1) | ||
223 | throw std::invalid_argument("Length is too small."); | ||
224 | |||
225 | int startidx = dstidx; | ||
226 | if (len < 0x21) | ||
227 | { | ||
228 | if ((dstidx + 2 + len) > dstlen) | ||
229 | throw std::runtime_error("Not enough space to store block."); | ||
230 | |||
231 | dst[dstidx++] = BLOCK_CODE | BLOCK_MODE | ((len - 1) & BLOCK_ARGS); | ||
232 | if ((dstidx ^ srcidx) & 1) | ||
233 | dst[dstidx++] = 0; | ||
234 | |||
235 | for (int i = 0; i < len; i++) | ||
236 | { | ||
237 | byte c = src[srcidx++]; | ||
238 | byte d = (c & 7) << 5; | ||
239 | c = (c & 0xF8) >> 3; | ||
240 | dst[dstidx++] = c | d; | ||
241 | } | ||
242 | } | ||
243 | else if (len < 0x2021) | ||
244 | { | ||
245 | if ((dstidx + 3 + len) > dstlen) | ||
246 | throw std::runtime_error("Not enough space to store block."); | ||
247 | |||
248 | dst[dstidx++] = BLOCK_CODE | (((len - 0x21) >> 8) & BLOCK_ARGS); | ||
249 | dst[dstidx++] = (len - 0x21) & 0xFF; | ||
250 | if ((dstidx ^ srcidx) & 1) | ||
251 | dst[dstidx++] = 0; | ||
252 | |||
253 | for (int i = 0; i < len; i++) | ||
254 | { | ||
255 | byte c = src[srcidx++]; | ||
256 | byte d = (c & 7) << 5; | ||
257 | c = (c & 0xF8) >> 3; | ||
258 | dst[dstidx++] = c | d; | ||
259 | } | ||
260 | } | ||
261 | else | ||
262 | { | ||
263 | int longblocks = len / 0x2020; | ||
264 | int rest = len % 0x2020; | ||
265 | for (int i = 0; i < longblocks; i++) | ||
266 | { | ||
267 | int tmp = encode_block(dst, dstidx, src, srcidx, 0x2020, dstlen); | ||
268 | if (!tmp) return 0; | ||
269 | } | ||
270 | if (rest) | ||
271 | { | ||
272 | int shortblocks = rest / 0x20; | ||
273 | for (int i = 0; i < shortblocks; i++) | ||
274 | { | ||
275 | int tmp = encode_block(dst, dstidx, src, srcidx, 0x20, dstlen); | ||
276 | if (!tmp) return 0; | ||
277 | } | ||
278 | rest = rest % 0x20; | ||
279 | int tmp = encode_block(dst, dstidx, src, srcidx, rest, dstlen); | ||
280 | if (!tmp) return 0; | ||
281 | } | ||
282 | } | ||
283 | |||
284 | return (dstidx - startidx); | ||
285 | } | ||
286 | }; //namespace | ||
287 | |||
288 | int zen::cenc_encode(byte* src, int srclen, byte* dst, int dstlen) | ||
289 | { | ||
290 | if (!src || !srclen || !dst || !dstlen) | ||
291 | { | ||
292 | throw std::invalid_argument("Invalid argument(s)."); | ||
293 | } | ||
294 | |||
295 | int i = 0, j = 0, k = 0; | ||
296 | word c, d, e; | ||
297 | int runlen = 0; | ||
298 | while (i < srclen && j < dstlen) | ||
299 | { | ||
300 | k = i; | ||
301 | c = src[i++]; | ||
302 | runlen = 1; | ||
303 | while (i < srclen && src[i] == c) | ||
304 | { | ||
305 | runlen++; | ||
306 | i++; | ||
307 | } | ||
308 | if (runlen >= 2) | ||
309 | { | ||
310 | if (!encode_run(dst, j, c, runlen, dstlen)) | ||
311 | return 0; | ||
312 | } | ||
313 | else | ||
314 | { | ||
315 | runlen = 0; | ||
316 | i = k; | ||
317 | while (i < (srclen - 1) && (src[i] != src[i + 1])) | ||
318 | { | ||
319 | runlen++; | ||
320 | i++; | ||
321 | } | ||
322 | if (i == (srclen - 1)) | ||
323 | { | ||
324 | runlen++; | ||
325 | i++; | ||
326 | } | ||
327 | if (!encode_block(dst, j, src, k, runlen, dstlen)) | ||
328 | return 0; | ||
329 | } | ||
330 | } | ||
331 | |||
332 | return j; | ||
333 | } | ||
diff --git a/utils/zenutils/source/shared/cenc.h b/utils/zenutils/source/shared/cenc.h new file mode 100755 index 0000000000..12a7c92516 --- /dev/null +++ b/utils/zenutils/source/shared/cenc.h | |||
@@ -0,0 +1,29 @@ | |||
1 | /* zenutils - Utilities for working with creative firmwares. | ||
2 | * Copyright 2007 (c) Rasmus Ry <rasmus.ry{at}gmail.com> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
17 | */ | ||
18 | |||
19 | #ifndef ZEN_CENC_H_INCLUDED | ||
20 | #define ZEN_CENC_H_INCLUDED | ||
21 | |||
22 | #include <utils.h> | ||
23 | |||
24 | namespace zen { | ||
25 | int cenc_decode(byte* src, int srclen, byte* dst, int dstlen); | ||
26 | int cenc_encode(byte* src, int srclen, byte* dst, int dstlen); | ||
27 | }; //namespace zen | ||
28 | |||
29 | #endif //CENC_H_INCLUDED | ||
diff --git a/utils/zenutils/source/shared/crypt.cpp b/utils/zenutils/source/shared/crypt.cpp new file mode 100755 index 0000000000..9c2d33870c --- /dev/null +++ b/utils/zenutils/source/shared/crypt.cpp | |||
@@ -0,0 +1,91 @@ | |||
1 | /* zenutils - Utilities for working with creative firmwares. | ||
2 | * Copyright 2007 (c) Rasmus Ry <rasmus.ry{at}gmail.com> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
17 | */ | ||
18 | |||
19 | #include "crypt.h" | ||
20 | #include <stdexcept> | ||
21 | #include <beecrypt/hmacsha1.h> | ||
22 | #include <beecrypt/blockmode.h> | ||
23 | #include <beecrypt/blowfish.h> | ||
24 | |||
25 | |||
26 | bool zen::hmac_sha1_calc(const byte* key, size_t keylen, const byte* data, | ||
27 | size_t datalen, byte* sig, size_t* siglen) | ||
28 | { | ||
29 | hmacsha1Param param; | ||
30 | if (hmacsha1Setup(¶m, key, keylen * 8)) | ||
31 | return false; | ||
32 | if (hmacsha1Update(¶m, data, datalen)) | ||
33 | return false; | ||
34 | if (hmacsha1Digest(¶m, sig)) | ||
35 | return false; | ||
36 | return true; | ||
37 | } | ||
38 | |||
39 | bool zen::bf_cbc_encrypt(const byte* key, size_t keylen, byte* data, | ||
40 | size_t datalen, const byte* iv) | ||
41 | { | ||
42 | if (datalen % blowfish.blocksize) | ||
43 | throw std::invalid_argument( | ||
44 | "The length must be aligned on a 8 byte boundary."); | ||
45 | |||
46 | blowfishParam param; | ||
47 | if (blowfishSetup(¶m, key, keylen * 8, ENCRYPT)) | ||
48 | return false; | ||
49 | if (blowfishSetIV(¶m, iv)) | ||
50 | return false; | ||
51 | |||
52 | byte* plain = new byte[datalen]; | ||
53 | memcpy(plain, data, datalen); | ||
54 | |||
55 | unsigned int nblocks = datalen / blowfish.blocksize; | ||
56 | if (blockEncryptCBC(&blowfish, ¶m, (uint32_t*)data, (uint32_t*)plain, | ||
57 | nblocks)) | ||
58 | { | ||
59 | delete [] plain; | ||
60 | return false; | ||
61 | } | ||
62 | |||
63 | return true; | ||
64 | } | ||
65 | |||
66 | bool zen::bf_cbc_decrypt(const byte* key, size_t keylen, byte* data, | ||
67 | size_t datalen, const byte* iv) | ||
68 | { | ||
69 | if (datalen % blowfish.blocksize) | ||
70 | throw std::invalid_argument( | ||
71 | "The length must be aligned on a 8 byte boundary."); | ||
72 | |||
73 | blowfishParam param; | ||
74 | if (blowfishSetup(¶m, key, keylen * 8, ENCRYPT)) | ||
75 | return false; | ||
76 | if (blowfishSetIV(¶m, iv)) | ||
77 | return false; | ||
78 | |||
79 | byte* cipher = new byte[datalen]; | ||
80 | memcpy(cipher, data, datalen); | ||
81 | |||
82 | unsigned int nblocks = datalen / blowfish.blocksize; | ||
83 | if (blockDecryptCBC(&blowfish, ¶m, (uint32_t*)data, (uint32_t*)cipher, | ||
84 | nblocks)) | ||
85 | { | ||
86 | delete [] cipher; | ||
87 | return false; | ||
88 | } | ||
89 | |||
90 | return true; | ||
91 | } | ||
diff --git a/utils/zenutils/source/shared/crypt.h b/utils/zenutils/source/shared/crypt.h new file mode 100755 index 0000000000..a057055b70 --- /dev/null +++ b/utils/zenutils/source/shared/crypt.h | |||
@@ -0,0 +1,30 @@ | |||
1 | /* zenutils - Utilities for working with creative firmwares. | ||
2 | * Copyright 2007 (c) Rasmus Ry <rasmus.ry{at}gmail.com> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
17 | */ | ||
18 | |||
19 | #ifndef ZEN_CRYPT_H_INCLUDED | ||
20 | #define ZEN_CRYPT_H_INCLUDED | ||
21 | |||
22 | #include <utils.h> | ||
23 | |||
24 | namespace zen { | ||
25 | bool hmac_sha1_calc(const byte* key, size_t keylen, const byte* data, size_t datalen, byte* sig, size_t* siglen); | ||
26 | bool bf_cbc_encrypt(const byte* key, size_t keylen, byte* data, size_t datalen, const byte* iv); | ||
27 | bool bf_cbc_decrypt(const byte* key, size_t keylen, byte* data, size_t datalen, const byte* iv); | ||
28 | }; //namespace zen | ||
29 | |||
30 | #endif //ZEN_CRYPT_H_INCLUDED | ||
diff --git a/utils/zenutils/source/shared/file.cpp b/utils/zenutils/source/shared/file.cpp new file mode 100755 index 0000000000..2c31498972 --- /dev/null +++ b/utils/zenutils/source/shared/file.cpp | |||
@@ -0,0 +1,106 @@ | |||
1 | /* zenutils - Utilities for working with creative firmwares. | ||
2 | * Copyright 2007 (c) Rasmus Ry <rasmus.ry{at}gmail.com> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
17 | */ | ||
18 | |||
19 | #include "file.h" | ||
20 | #include <fstream> | ||
21 | |||
22 | |||
23 | bool shared::read_file(const std::string& filename, bytes& buffer, | ||
24 | std::streampos offset, std::streamsize count) | ||
25 | { | ||
26 | std::ifstream ifs; | ||
27 | ifs.open(filename.c_str(), std::ios::binary); | ||
28 | if (!ifs) | ||
29 | { | ||
30 | return false; | ||
31 | } | ||
32 | |||
33 | std::ifstream::pos_type startpos = offset; | ||
34 | ifs.seekg(offset, std::ios::beg); | ||
35 | if (count == -1) | ||
36 | ifs.seekg(0, std::ios::end); | ||
37 | else | ||
38 | ifs.seekg(count, std::ios::cur); | ||
39 | std::ifstream::pos_type endpos = ifs.tellg(); | ||
40 | |||
41 | buffer.resize(endpos-startpos); | ||
42 | ifs.seekg(offset, std::ios::beg); | ||
43 | |||
44 | ifs.read((char*)&buffer[0], endpos-startpos); | ||
45 | |||
46 | ifs.close(); | ||
47 | return ifs.good(); | ||
48 | } | ||
49 | |||
50 | |||
51 | bool shared::write_file(const std::string& filename, bytes& buffer, | ||
52 | bool truncate, std::streampos offset, | ||
53 | std::streamsize count) | ||
54 | { | ||
55 | std::ios::openmode mode = std::ios::in|std::ios::out|std::ios::binary; | ||
56 | if (truncate) | ||
57 | mode |= std::ios::trunc; | ||
58 | |||
59 | std::fstream ofs; | ||
60 | ofs.open(filename.c_str(), mode); | ||
61 | if (!ofs) | ||
62 | { | ||
63 | return false; | ||
64 | } | ||
65 | |||
66 | if (count == -1) | ||
67 | count = buffer.size(); | ||
68 | else if (count > buffer.size()) | ||
69 | return false; | ||
70 | |||
71 | ofs.seekg(offset, std::ios::beg); | ||
72 | |||
73 | ofs.write((char*)&buffer[0], count); | ||
74 | |||
75 | ofs.close(); | ||
76 | return ofs.good(); | ||
77 | } | ||
78 | |||
79 | bool shared::file_exists(const std::string& filename) | ||
80 | { | ||
81 | std::ifstream ifs; | ||
82 | ifs.open(filename.c_str(), std::ios::in); | ||
83 | if (ifs.is_open()) | ||
84 | { | ||
85 | ifs.close(); | ||
86 | return true; | ||
87 | } | ||
88 | return false; | ||
89 | } | ||
90 | |||
91 | bool shared::copy_file(const std::string& srcname, const std::string& dstname) | ||
92 | { | ||
93 | bytes buffer; | ||
94 | if (!read_file(srcname, buffer)) | ||
95 | return false; | ||
96 | return write_file(dstname, buffer, true); | ||
97 | } | ||
98 | |||
99 | bool shared::backup_file(const std::string& filename, bool force) | ||
100 | { | ||
101 | std::string backupname = filename + ".bak"; | ||
102 | if (!force) | ||
103 | if (file_exists(backupname)) | ||
104 | return true; | ||
105 | return copy_file(filename, backupname); | ||
106 | } | ||
diff --git a/utils/zenutils/source/shared/file.h b/utils/zenutils/source/shared/file.h new file mode 100755 index 0000000000..8fa533c981 --- /dev/null +++ b/utils/zenutils/source/shared/file.h | |||
@@ -0,0 +1,36 @@ | |||
1 | /* zenutils - Utilities for working with creative firmwares. | ||
2 | * Copyright 2007 (c) Rasmus Ry <rasmus.ry{at}gmail.com> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
17 | */ | ||
18 | |||
19 | #ifndef SHARED_FILE_H_INCLUDED | ||
20 | #define SHARED_FILE_H_INCLUDED | ||
21 | |||
22 | #include <string> | ||
23 | #include <iostream> | ||
24 | #include "utils.h" | ||
25 | |||
26 | namespace shared { | ||
27 | bool read_file(const std::string& filename, bytes& buffer, | ||
28 | std::streampos offset = 0, std::streamsize count = -1); | ||
29 | bool write_file(const std::string& filename, bytes& buffer, bool truncate, | ||
30 | std::streampos offset = 0, std::streamsize count = -1); | ||
31 | bool file_exists(const std::string& filename); | ||
32 | bool copy_file(const std::string& srcname, const std::string& dstname); | ||
33 | bool backup_file(const std::string& filename, bool force = false); | ||
34 | }; //namespace shared | ||
35 | |||
36 | #endif //SHARED_FILE_H_INCLUDED | ||
diff --git a/utils/zenutils/source/shared/firmware.cpp b/utils/zenutils/source/shared/firmware.cpp new file mode 100755 index 0000000000..7767b55d8f --- /dev/null +++ b/utils/zenutils/source/shared/firmware.cpp | |||
@@ -0,0 +1,387 @@ | |||
1 | /* zenutils - Utilities for working with creative firmwares. | ||
2 | * Copyright 2007 (c) Rasmus Ry <rasmus.ry{at}gmail.com> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
17 | */ | ||
18 | |||
19 | #include "firmware.h" | ||
20 | #include <iostream> | ||
21 | #include <stdexcept> | ||
22 | |||
23 | |||
24 | zen::firmware_entry::firmware_entry(bool big_endian) | ||
25 | : _big_endian(big_endian) | ||
26 | { | ||
27 | } | ||
28 | |||
29 | zen::firmware_entry::firmware_entry(const firmware_entry& copy) | ||
30 | { | ||
31 | assign(copy); | ||
32 | } | ||
33 | |||
34 | zen::firmware_entry& zen::firmware_entry::operator=(const firmware_entry& right) | ||
35 | { | ||
36 | assign(right); | ||
37 | return *this; | ||
38 | } | ||
39 | |||
40 | |||
41 | bool zen::firmware_entry::read(std::istream& is) | ||
42 | { | ||
43 | // Read the header. | ||
44 | is.read((char*)&_header, sizeof(firmware_header_t)); | ||
45 | if (!is.good()) | ||
46 | return false; | ||
47 | |||
48 | // If the firmware is big-endian, swap the header values to little-endian. | ||
49 | if (_big_endian) | ||
50 | { | ||
51 | _header.tag = shared::swap(_header.tag); | ||
52 | if (_header.tag != 'NULL') | ||
53 | { | ||
54 | _header.size = shared::swap(_header.size); | ||
55 | } | ||
56 | } | ||
57 | |||
58 | // Resize the bytes buffer to the size specified in the header. | ||
59 | _bytes.resize(_header.size); | ||
60 | |||
61 | // Read the entry contents. | ||
62 | is.read(reinterpret_cast<char*>(&_bytes[0]), | ||
63 | _header.size); | ||
64 | |||
65 | return is.good(); | ||
66 | } | ||
67 | |||
68 | bool zen::firmware_entry::write(std::ostream& os) const | ||
69 | { | ||
70 | // Form a header using the current size of the bytes buffer. | ||
71 | firmware_header_t header = { | ||
72 | _header.tag, | ||
73 | static_cast<dword>(_bytes.size()) | ||
74 | }; | ||
75 | |||
76 | // If the firmware is big-endian, swap the header values back into big-endian. | ||
77 | if (_big_endian) | ||
78 | { | ||
79 | if (header.tag != 'NULL') | ||
80 | { | ||
81 | header.size = shared::swap(header.size); | ||
82 | } | ||
83 | header.tag = shared::swap(header.tag); | ||
84 | } | ||
85 | |||
86 | // Write the header. | ||
87 | os.write((const char*)&header, sizeof(firmware_header_t)); | ||
88 | if (!os.good()) | ||
89 | return false; | ||
90 | |||
91 | // Write the entry contents. | ||
92 | os.write(reinterpret_cast<const char*>(&_bytes[0]), | ||
93 | static_cast<std::streamsize>(_bytes.size())); | ||
94 | |||
95 | return os.good(); | ||
96 | } | ||
97 | |||
98 | |||
99 | bool zen::firmware_entry::is_big_endian() const | ||
100 | { | ||
101 | return _big_endian; | ||
102 | } | ||
103 | |||
104 | const zen::firmware_header_t& zen::firmware_entry::get_header() const | ||
105 | { | ||
106 | return _header; | ||
107 | } | ||
108 | zen::firmware_header_t& zen::firmware_entry::get_header() | ||
109 | { | ||
110 | return _header; | ||
111 | } | ||
112 | |||
113 | const shared::bytes& zen::firmware_entry::get_bytes() const | ||
114 | { | ||
115 | return _bytes; | ||
116 | } | ||
117 | shared::bytes& zen::firmware_entry::get_bytes() | ||
118 | { | ||
119 | return _bytes; | ||
120 | } | ||
121 | |||
122 | |||
123 | std::string zen::firmware_entry::get_name() const | ||
124 | { | ||
125 | char name[5]; | ||
126 | *(dword*)name = shared::swap(_header.tag); | ||
127 | name[4] = '\0'; | ||
128 | |||
129 | // Determine if all characters in the tag are printable. | ||
130 | bool isprintable = true; | ||
131 | for (int i = 0; i < 4; i++) | ||
132 | { | ||
133 | if (!isprint((byte)name[i])) | ||
134 | { | ||
135 | isprintable = false; | ||
136 | break; | ||
137 | } | ||
138 | } | ||
139 | |||
140 | // If they are, simply return the tag as a string. | ||
141 | if (isprintable) | ||
142 | { | ||
143 | return std::string(name); | ||
144 | } | ||
145 | |||
146 | // Otherwise, encode the tag into a hexadecimal string. | ||
147 | char buffer[11]; | ||
148 | sprintf(buffer, "0x%08x", _header.tag); | ||
149 | return std::string(buffer); | ||
150 | } | ||
151 | |||
152 | std::string zen::firmware_entry::get_content_name() const | ||
153 | { | ||
154 | std::string name = get_name(); | ||
155 | if (name == "DATA") | ||
156 | { | ||
157 | name = ""; | ||
158 | int nameoff = is_big_endian() ? 1 : 0; | ||
159 | for (int i = 0; i < 16; i++) | ||
160 | { | ||
161 | char c = get_bytes()[i * 2 + nameoff]; | ||
162 | if (!c) | ||
163 | break; | ||
164 | name += c; | ||
165 | } | ||
166 | } | ||
167 | else if (name == "EXT0") | ||
168 | { | ||
169 | name = ""; | ||
170 | int nameoff = is_big_endian() ? 1 : 0; | ||
171 | for (int i = 0; i < 12; i++) | ||
172 | { | ||
173 | char c = get_bytes()[i * 2 + nameoff]; | ||
174 | if (!c) | ||
175 | break; | ||
176 | name += c; | ||
177 | } | ||
178 | } | ||
179 | return name; | ||
180 | } | ||
181 | |||
182 | size_t zen::firmware_entry::get_content_offset() const | ||
183 | { | ||
184 | std::string name = get_name(); | ||
185 | if (name == "DATA") | ||
186 | { | ||
187 | return 32; | ||
188 | } | ||
189 | else if (name == "EXT0") | ||
190 | { | ||
191 | return 24; | ||
192 | } | ||
193 | return 0; | ||
194 | } | ||
195 | |||
196 | size_t zen::firmware_entry::calc_size() const | ||
197 | { | ||
198 | return _bytes.size() + sizeof(firmware_header_t); | ||
199 | } | ||
200 | |||
201 | |||
202 | void zen::firmware_entry::assign(const firmware_entry& copy) | ||
203 | { | ||
204 | _big_endian = copy._big_endian; | ||
205 | _header.tag = copy._header.tag; | ||
206 | _header.size = copy._header.size; | ||
207 | _bytes.assign(copy._bytes.begin(), copy._bytes.end()); | ||
208 | } | ||
209 | |||
210 | |||
211 | |||
212 | zen::firmware_archive::firmware_archive(bool big_endian) | ||
213 | : _big_endian(big_endian) | ||
214 | { | ||
215 | } | ||
216 | |||
217 | zen::firmware_archive::firmware_archive(const firmware_archive& copy) | ||
218 | { | ||
219 | assign(copy); | ||
220 | } | ||
221 | |||
222 | zen::firmware_archive& zen::firmware_archive::operator=(const firmware_archive& right) | ||
223 | { | ||
224 | assign(right); | ||
225 | return *this; | ||
226 | } | ||
227 | |||
228 | |||
229 | bool zen::firmware_archive::read(std::istream& is) | ||
230 | { | ||
231 | // Read the root entry's header. | ||
232 | firmware_header_t root; | ||
233 | is.read((char*)&root, sizeof(firmware_header_t)); | ||
234 | if (!is.good()) | ||
235 | return false; | ||
236 | |||
237 | if ((root.tag != 'CIFF') && (root.tag != 'FFIC')) | ||
238 | { | ||
239 | throw std::runtime_error("Invalid firmware archive format!"); | ||
240 | } | ||
241 | |||
242 | _big_endian = root.tag == 'FFIC' ? true : false; | ||
243 | if (_big_endian) | ||
244 | { | ||
245 | root.tag = shared::swap(root.tag); | ||
246 | root.size = shared::swap(root.size); | ||
247 | } | ||
248 | |||
249 | // Save the current stream position. | ||
250 | std::istream::pos_type endpos = is.tellg(); | ||
251 | std::istream::pos_type curpos = endpos; | ||
252 | endpos += std::istream::pos_type(root.size); | ||
253 | |||
254 | // Read untill the end of the root entry contents. | ||
255 | while (curpos < endpos) | ||
256 | { | ||
257 | firmware_entry entry(_big_endian); | ||
258 | if (!entry.read(is)) | ||
259 | return false; | ||
260 | |||
261 | _children.push_back(entry); | ||
262 | curpos = is.tellg(); | ||
263 | } | ||
264 | |||
265 | curpos = is.tellg(); | ||
266 | is.seekg(0, std::ios::end); | ||
267 | endpos = is.tellg(); | ||
268 | is.seekg(curpos); | ||
269 | |||
270 | // Read untill the end of the file. | ||
271 | while (((size_t)curpos + sizeof(firmware_header_t)) < endpos) | ||
272 | { | ||
273 | firmware_entry entry(_big_endian); | ||
274 | if (!entry.read(is)) | ||
275 | return false; | ||
276 | |||
277 | _neighbours.push_back(entry); | ||
278 | curpos = is.tellg(); | ||
279 | } | ||
280 | |||
281 | return true; | ||
282 | } | ||
283 | |||
284 | bool zen::firmware_archive::write(std::ostream& os) const | ||
285 | { | ||
286 | // Read the root entry's header. | ||
287 | firmware_header_t root = {'CIFF', 0}; | ||
288 | |||
289 | // Calculate the total size of all the children entries. | ||
290 | for (firmware_entries::const_iterator i = _children.begin(); | ||
291 | i != _children.end(); ++i) | ||
292 | { | ||
293 | root.size += i->calc_size(); | ||
294 | } | ||
295 | |||
296 | // If the firmware is big-endian, swap the header values back into big-endian. | ||
297 | if (_big_endian) | ||
298 | { | ||
299 | root.tag = shared::swap(root.tag); | ||
300 | root.size = shared::swap(root.size); | ||
301 | } | ||
302 | |||
303 | // Write the header. | ||
304 | os.write((const char*)&root, sizeof(firmware_header_t)); | ||
305 | if (!os.good()) | ||
306 | return false; | ||
307 | |||
308 | // Write all the child entries. | ||
309 | for (firmware_entries::const_iterator i = _children.begin(); | ||
310 | i != _children.end(); ++i) | ||
311 | { | ||
312 | if (!i->write(os)) | ||
313 | return false; | ||
314 | } | ||
315 | |||
316 | // Write all the neighbour entries. | ||
317 | for (firmware_entries::const_iterator i = _neighbours.begin(); | ||
318 | i != _neighbours.end(); ++i) | ||
319 | { | ||
320 | if (!i->write(os)) | ||
321 | return false; | ||
322 | } | ||
323 | |||
324 | return true; | ||
325 | } | ||
326 | |||
327 | |||
328 | bool zen::firmware_archive::is_big_endian() const | ||
329 | { | ||
330 | return _big_endian; | ||
331 | } | ||
332 | |||
333 | const zen::firmware_entries& zen::firmware_archive::get_children() const | ||
334 | { | ||
335 | return _children; | ||
336 | } | ||
337 | zen::firmware_entries& zen::firmware_archive::get_children() | ||
338 | { | ||
339 | return _children; | ||
340 | } | ||
341 | |||
342 | const zen::firmware_entries& zen::firmware_archive::get_neighbours() const | ||
343 | { | ||
344 | return _neighbours; | ||
345 | } | ||
346 | zen::firmware_entries& zen::firmware_archive::get_neighbours() | ||
347 | { | ||
348 | return _neighbours; | ||
349 | } | ||
350 | |||
351 | bool zen::firmware_archive::is_signed() const | ||
352 | { | ||
353 | for (firmware_entries::const_iterator i = _neighbours.begin(); | ||
354 | i != _neighbours.end(); i++) | ||
355 | { | ||
356 | if (i->get_name() == "NULL") | ||
357 | return true; | ||
358 | } | ||
359 | return false; | ||
360 | } | ||
361 | |||
362 | size_t zen::firmware_archive::calc_size() const | ||
363 | { | ||
364 | size_t size = sizeof(firmware_header_t); | ||
365 | |||
366 | for (firmware_entries::const_iterator i = _children.begin(); | ||
367 | i != _children.end(); i++) | ||
368 | { | ||
369 | size += i->calc_size(); | ||
370 | } | ||
371 | |||
372 | for (firmware_entries::const_iterator i = _neighbours.begin(); | ||
373 | i != _neighbours.end(); i++) | ||
374 | { | ||
375 | size += i->calc_size(); | ||
376 | } | ||
377 | |||
378 | return size; | ||
379 | } | ||
380 | |||
381 | |||
382 | void zen::firmware_archive::assign(const firmware_archive& copy) | ||
383 | { | ||
384 | _big_endian = copy._big_endian; | ||
385 | _children.assign(copy._children.begin(), copy._children.end()); | ||
386 | _neighbours.assign(copy._neighbours.begin(), copy._neighbours.end()); | ||
387 | } | ||
diff --git a/utils/zenutils/source/shared/firmware.h b/utils/zenutils/source/shared/firmware.h new file mode 100755 index 0000000000..3542186590 --- /dev/null +++ b/utils/zenutils/source/shared/firmware.h | |||
@@ -0,0 +1,92 @@ | |||
1 | /* zenutils - Utilities for working with creative firmwares. | ||
2 | * Copyright 2007 (c) Rasmus Ry <rasmus.ry{at}gmail.com> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
17 | */ | ||
18 | |||
19 | #ifndef ZEN_FIRMWARE_H_INCLUDED | ||
20 | #define ZEN_FIRMWARE_H_INCLUDED | ||
21 | |||
22 | #include <list> | ||
23 | #include <utils.h> | ||
24 | |||
25 | namespace zen { | ||
26 | struct firmware_header_t | ||
27 | { | ||
28 | dword tag; | ||
29 | dword size; | ||
30 | }; //struct firmware_header_t | ||
31 | |||
32 | class firmware_entry | ||
33 | { | ||
34 | public: | ||
35 | firmware_entry(bool big_endian); | ||
36 | firmware_entry(const firmware_entry& copy); | ||
37 | firmware_entry& operator=(const firmware_entry& right); | ||
38 | |||
39 | bool read(std::istream& is); | ||
40 | bool write(std::ostream& os) const; | ||
41 | |||
42 | bool is_big_endian() const; | ||
43 | const firmware_header_t& get_header() const; | ||
44 | firmware_header_t& get_header(); | ||
45 | const shared::bytes& get_bytes() const; | ||
46 | shared::bytes& get_bytes(); | ||
47 | |||
48 | std::string get_name() const; | ||
49 | std::string get_content_name() const; | ||
50 | size_t get_content_offset() const; | ||
51 | size_t calc_size() const; | ||
52 | |||
53 | protected: | ||
54 | void assign(const firmware_entry& copy); | ||
55 | |||
56 | private: | ||
57 | bool _big_endian; | ||
58 | firmware_header_t _header; | ||
59 | shared::bytes _bytes; | ||
60 | }; //class firmware_entry | ||
61 | |||
62 | typedef std::list<firmware_entry> firmware_entries; | ||
63 | |||
64 | class firmware_archive | ||
65 | { | ||
66 | public: | ||
67 | firmware_archive(bool big_endian); | ||
68 | firmware_archive(const firmware_archive& copy); | ||
69 | firmware_archive& operator=(const firmware_archive& right); | ||
70 | |||
71 | bool read(std::istream& is); | ||
72 | bool write(std::ostream& os) const; | ||
73 | |||
74 | bool is_big_endian() const; | ||
75 | const firmware_entries& get_children() const; | ||
76 | firmware_entries& get_children(); | ||
77 | const firmware_entries& get_neighbours() const; | ||
78 | firmware_entries& get_neighbours(); | ||
79 | bool is_signed() const; | ||
80 | size_t calc_size() const; | ||
81 | |||
82 | protected: | ||
83 | void assign(const firmware_archive& copy); | ||
84 | |||
85 | private: | ||
86 | firmware_entries _children; | ||
87 | firmware_entries _neighbours; | ||
88 | bool _big_endian; | ||
89 | }; //class firmware_archive | ||
90 | }; //namespace zen | ||
91 | |||
92 | #endif //ZEN_FIRMWARE_ARCHIVE_H_INCLUDED | ||
diff --git a/utils/zenutils/source/shared/pe.cpp b/utils/zenutils/source/shared/pe.cpp new file mode 100755 index 0000000000..c86ec6c8cc --- /dev/null +++ b/utils/zenutils/source/shared/pe.cpp | |||
@@ -0,0 +1,128 @@ | |||
1 | /* zenutils - Utilities for working with creative firmwares. | ||
2 | * Copyright 2007 (c) Rasmus Ry <rasmus.ry{at}gmail.com> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
17 | */ | ||
18 | |||
19 | #include "pe.h" | ||
20 | |||
21 | |||
22 | shared::pe_file::pe_file(PeLib::PeFile* pef) : _pef(pef) | ||
23 | { | ||
24 | } | ||
25 | shared::pe_file::~pe_file() | ||
26 | { | ||
27 | if (_pef != NULL) | ||
28 | delete _pef; | ||
29 | } | ||
30 | |||
31 | bool shared::pe_file::is_valid() const | ||
32 | { | ||
33 | if (_pef->getBits() == 32) | ||
34 | { | ||
35 | PeLib::PeHeader32& pef32 = static_cast<PeLib::PeFile32*>(_pef)->peHeader(); | ||
36 | if (!pef32.isValid()) | ||
37 | return false; | ||
38 | return true; | ||
39 | } | ||
40 | else if (_pef->getBits() == 64) | ||
41 | { | ||
42 | PeLib::PeHeader64& pef64 = static_cast<PeLib::PeFile64*>(_pef)->peHeader(); | ||
43 | if (!pef64.isValid()) | ||
44 | return false; | ||
45 | return true; | ||
46 | } | ||
47 | return false; | ||
48 | } | ||
49 | |||
50 | bool shared::pe_file::read(const std::string& filename) | ||
51 | { | ||
52 | if (_pef != NULL) | ||
53 | { | ||
54 | delete _pef; | ||
55 | _pef = NULL; | ||
56 | } | ||
57 | |||
58 | _pef = PeLib::openPeFile(filename); | ||
59 | if (!_pef) | ||
60 | { | ||
61 | return false; | ||
62 | } | ||
63 | if (_pef->readMzHeader()) | ||
64 | { | ||
65 | delete _pef; | ||
66 | return false; | ||
67 | } | ||
68 | if (!_pef->mzHeader().isValid()) | ||
69 | { | ||
70 | delete _pef; | ||
71 | return false; | ||
72 | } | ||
73 | if (_pef->readPeHeader()) | ||
74 | { | ||
75 | delete _pef; | ||
76 | return false; | ||
77 | } | ||
78 | if (!is_valid()) | ||
79 | { | ||
80 | delete _pef; | ||
81 | return false; | ||
82 | } | ||
83 | return true; | ||
84 | } | ||
85 | |||
86 | bool shared::pe_file::find_section(const std::string& name, section_info& info) const | ||
87 | { | ||
88 | if (_pef->getBits() == 32) | ||
89 | return find_section(static_cast<PeLib::PeFile32*>(_pef), | ||
90 | name, info); | ||
91 | else if (_pef->getBits() == 64) | ||
92 | return find_section(static_cast<PeLib::PeFile64*>(_pef), | ||
93 | name, info); | ||
94 | return false; | ||
95 | } | ||
96 | |||
97 | bool shared::pe_file::add_section(const std::string& name, | ||
98 | const bytes& buffer, section_info& info) | ||
99 | { | ||
100 | if (_pef->getBits() == 32) | ||
101 | { | ||
102 | return add_section(static_cast<PeLib::PeFile32*>(_pef), | ||
103 | name, buffer, info); | ||
104 | } | ||
105 | else if (_pef->getBits() == 64) | ||
106 | { | ||
107 | return add_section(static_cast<PeLib::PeFile64*>(_pef), | ||
108 | name, buffer, info); | ||
109 | } | ||
110 | return false; | ||
111 | } | ||
112 | |||
113 | dword shared::pe_file::get_image_base() const | ||
114 | { | ||
115 | if (_pef->getBits() == 32) | ||
116 | return static_cast<PeLib::PeFile32*>(_pef)->peHeader().getImageBase(); | ||
117 | else | ||
118 | return static_cast<PeLib::PeFile64*>(_pef)->peHeader().getImageBase(); | ||
119 | return 0; | ||
120 | } | ||
121 | dword shared::pe_file::pa_to_va(dword pa) const | ||
122 | { | ||
123 | if (_pef->getBits() == 32) | ||
124 | return static_cast<PeLib::PeFile32*>(_pef)->peHeader().offsetToVa(pa); | ||
125 | else | ||
126 | return static_cast<PeLib::PeFile64*>(_pef)->peHeader().offsetToVa(pa); | ||
127 | return 0; | ||
128 | } | ||
diff --git a/utils/zenutils/source/shared/pe.h b/utils/zenutils/source/shared/pe.h new file mode 100755 index 0000000000..92a272d3c7 --- /dev/null +++ b/utils/zenutils/source/shared/pe.h | |||
@@ -0,0 +1,142 @@ | |||
1 | /* zenutils - Utilities for working with creative firmwares. | ||
2 | * Copyright 2007 (c) Rasmus Ry <rasmus.ry{at}gmail.com> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
17 | */ | ||
18 | |||
19 | #ifndef SHARED_PE_H_INCLUDED | ||
20 | #define SHARED_PE_H_INCLUDED | ||
21 | |||
22 | #include <string> | ||
23 | #include <pelib/PeLib.h> | ||
24 | #include <utils.h> | ||
25 | |||
26 | namespace shared { | ||
27 | struct section_info | ||
28 | { | ||
29 | word index; | ||
30 | dword virtual_address; | ||
31 | dword virtual_size; | ||
32 | dword raw_address; | ||
33 | dword raw_size; | ||
34 | dword characteristics; | ||
35 | }; //struct section_info | ||
36 | |||
37 | class pe_file | ||
38 | { | ||
39 | public: | ||
40 | pe_file(PeLib::PeFile* pef = NULL); | ||
41 | ~pe_file(); | ||
42 | |||
43 | bool is_valid() const; | ||
44 | bool read(const std::string& filename); | ||
45 | bool find_section(const std::string& name, section_info& info) const; | ||
46 | bool add_section(const std::string& name, const bytes& buffer, section_info& info); | ||
47 | dword get_image_base() const; | ||
48 | dword pa_to_va(PeLib::dword pa) const; | ||
49 | |||
50 | protected: | ||
51 | template <int _Bits> | ||
52 | static bool find_section(const PeLib::PeFileT<_Bits>* pef, | ||
53 | const std::string& name, section_info& info); | ||
54 | template <int _Bits> | ||
55 | static bool add_section(PeLib::PeFileT<_Bits>* pef, | ||
56 | const std::string& name, const bytes& buffer, | ||
57 | section_info& info); | ||
58 | |||
59 | private: | ||
60 | PeLib::PeFile* _pef; | ||
61 | }; //class pe_file | ||
62 | |||
63 | |||
64 | template <int _Bits> | ||
65 | bool pe_file::find_section(const PeLib::PeFileT<_Bits>* pef, | ||
66 | const std::string& name, section_info& info) | ||
67 | { | ||
68 | for (PeLib::word i = 0; i < pef->peHeader().getNumberOfSections(); i++) | ||
69 | { | ||
70 | if (pef->peHeader().getSectionName(i) == name) | ||
71 | { | ||
72 | info.index = i; | ||
73 | info.virtual_address = pef->peHeader().getVirtualAddress(i); | ||
74 | info.virtual_size = pef->peHeader().getVirtualSize(i); | ||
75 | info.raw_address = pef->peHeader().getPointerToRawData(i); | ||
76 | info.raw_size = pef->peHeader().getSizeOfRawData(i); | ||
77 | info.characteristics = pef->peHeader().getCharacteristics(i); | ||
78 | return true; | ||
79 | } | ||
80 | } | ||
81 | return false; | ||
82 | } | ||
83 | |||
84 | template <int _Bits> | ||
85 | bool pe_file::add_section(PeLib::PeFileT<_Bits>* pef, | ||
86 | const std::string& name, const bytes& buffer, | ||
87 | section_info& info) | ||
88 | { | ||
89 | using namespace PeLib; | ||
90 | |||
91 | // Check if the last section has the same name as the one being added. | ||
92 | PeLib::word secnum = pef->peHeader().getNumberOfSections(); | ||
93 | if (pef->peHeader().getSectionName(secnum-1) == name) | ||
94 | { | ||
95 | // If it is, we change the attributes of the existing section. | ||
96 | secnum = secnum - 1; | ||
97 | pef->peHeader().setSizeOfRawData(secnum, | ||
98 | alignOffset(buffer.size(), | ||
99 | pef->peHeader().getFileAlignment())); | ||
100 | pef->peHeader().setVirtualSize(secnum, | ||
101 | alignOffset(buffer.size(), | ||
102 | pef->peHeader().getSectionAlignment())); | ||
103 | PeLib::dword chars = pef->peHeader().getCharacteristics(secnum-1); | ||
104 | pef->peHeader().setCharacteristics(secnum, | ||
105 | chars | PELIB_IMAGE_SCN_MEM_WRITE | PELIB_IMAGE_SCN_MEM_READ); | ||
106 | } | ||
107 | else | ||
108 | { | ||
109 | // Otherwise we add a new section. | ||
110 | if (pef->peHeader().addSection(name, buffer.size()) != NO_ERROR) | ||
111 | { | ||
112 | return false; | ||
113 | } | ||
114 | pef->peHeader().makeValid(pef->mzHeader().getAddressOfPeHeader()); | ||
115 | pef->peHeader().write(pef->getFileName(), pef->mzHeader().getAddressOfPeHeader()); | ||
116 | } | ||
117 | |||
118 | // Save the section headers to the file. | ||
119 | if (pef->peHeader().writeSections(pef->getFileName()) != NO_ERROR) | ||
120 | { | ||
121 | return false; | ||
122 | } | ||
123 | |||
124 | // Save the section data to the file. | ||
125 | if (pef->peHeader().writeSectionData(pef->getFileName(), secnum, buffer) != NO_ERROR) | ||
126 | { | ||
127 | return false; | ||
128 | } | ||
129 | |||
130 | // Fill out the section information. | ||
131 | info.index = secnum; | ||
132 | info.virtual_address = pef->peHeader().getVirtualAddress(secnum); | ||
133 | info.virtual_size = pef->peHeader().getVirtualSize(secnum); | ||
134 | info.raw_address = pef->peHeader().getPointerToRawData(secnum); | ||
135 | info.raw_size = pef->peHeader().getSizeOfRawData(secnum); | ||
136 | info.characteristics = pef->peHeader().getCharacteristics(secnum); | ||
137 | |||
138 | return true; | ||
139 | } | ||
140 | }; //namespace shared | ||
141 | |||
142 | #endif //SHARED_PE_H_INCLUDED | ||
diff --git a/utils/zenutils/source/shared/shared.cpp b/utils/zenutils/source/shared/shared.cpp new file mode 100755 index 0000000000..e69de29bb2 --- /dev/null +++ b/utils/zenutils/source/shared/shared.cpp | |||
diff --git a/utils/zenutils/source/shared/updater.cpp b/utils/zenutils/source/shared/updater.cpp new file mode 100755 index 0000000000..77d3f2876c --- /dev/null +++ b/utils/zenutils/source/shared/updater.cpp | |||
@@ -0,0 +1,151 @@ | |||
1 | /* zenutils - Utilities for working with creative firmwares. | ||
2 | * Copyright 2007 (c) Rasmus Ry <rasmus.ry{at}gmail.com> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
17 | */ | ||
18 | |||
19 | #include "updater.h" | ||
20 | #include <file.h> | ||
21 | #include <pe.h> | ||
22 | #include <utils.h> | ||
23 | |||
24 | |||
25 | const char* zen::find_firmware_key(const byte* buffer, size_t len) | ||
26 | { | ||
27 | char szkey1[] = "34d1"; | ||
28 | size_t cchkey1 = strlen(szkey1); | ||
29 | char szkey2[] = "TbnCboEbn"; | ||
30 | size_t cchkey2 = strlen(szkey2); | ||
31 | for (int i = 0; i < static_cast<int>(len); i++) | ||
32 | { | ||
33 | if (len >= cchkey1) | ||
34 | { | ||
35 | if (!strncmp((char*)&buffer[i], szkey1, cchkey1)) | ||
36 | { | ||
37 | return (const char*)&buffer[i]; | ||
38 | } | ||
39 | } | ||
40 | if (len >= cchkey2) | ||
41 | { | ||
42 | if (!strncmp((char*)&buffer[i], szkey2, cchkey2)) | ||
43 | { | ||
44 | return (const char*)&buffer[i]; | ||
45 | } | ||
46 | } | ||
47 | } | ||
48 | return NULL; | ||
49 | } | ||
50 | |||
51 | dword zen::find_firmware_offset(byte* buffer, size_t len) | ||
52 | { | ||
53 | for (dword i = 0; i < static_cast<dword>(len); i += 0x10) | ||
54 | { | ||
55 | dword size = *(dword*)&buffer[i]; | ||
56 | if (size < (i + len) && size > (len >> 1)) | ||
57 | { | ||
58 | if (buffer[i + sizeof(dword)] != 0 | ||
59 | && buffer[i + sizeof(dword) + 1] != 0 | ||
60 | && buffer[i + sizeof(dword) + 2] != 0 | ||
61 | && buffer[i + sizeof(dword) + 3] != 0) | ||
62 | { | ||
63 | return i; | ||
64 | } | ||
65 | } | ||
66 | } | ||
67 | return 0; | ||
68 | } | ||
69 | |||
70 | bool zen::find_firmware_archive(const std::string& filename, dword& va, dword& pa) | ||
71 | { | ||
72 | shared::pe_file pef; | ||
73 | if (!pef.read(filename)) | ||
74 | { | ||
75 | return false; | ||
76 | } | ||
77 | shared::section_info data_section; | ||
78 | if (!pef.find_section(".data", data_section)) | ||
79 | { | ||
80 | return false; | ||
81 | } | ||
82 | shared::bytes buffer; | ||
83 | if (!shared::read_file(filename, buffer, data_section.raw_address, | ||
84 | data_section.raw_size)) | ||
85 | { | ||
86 | return false; | ||
87 | } | ||
88 | dword offset = find_firmware_offset(&buffer[0], buffer.size()); | ||
89 | if (!offset) | ||
90 | { | ||
91 | return false; | ||
92 | } | ||
93 | va = data_section.virtual_address + offset; | ||
94 | pa = data_section.raw_address + offset; | ||
95 | |||
96 | return true; | ||
97 | } | ||
98 | |||
99 | |||
100 | bool zen::crypt_firmware(const char* key, byte* buffer, size_t len) | ||
101 | { | ||
102 | // Determine if the key length is dword aligned. | ||
103 | int keylen = strlen(key); | ||
104 | int keylen_rem = keylen % sizeof(dword); | ||
105 | |||
106 | // Determine how many times the key must be repeated to be dword aligned. | ||
107 | int keycycle = keylen_rem ? (sizeof(dword) / keylen_rem) : 1; | ||
108 | int keyscount = (keylen * keycycle) / sizeof(dword); | ||
109 | |||
110 | // Allocate a buffer to hold the key as an array of dwords. | ||
111 | dword* keys = new dword[keyscount]; | ||
112 | |||
113 | // Copy the key into the key array, whilst mutating it. | ||
114 | for (int i = 0; i < keyscount; i++) | ||
115 | { | ||
116 | dword val; | ||
117 | int keyoffset = (i * sizeof(dword)) % keylen; | ||
118 | if ((keyoffset+sizeof(dword)) < keylen) | ||
119 | { | ||
120 | val = *(dword*)&key[keyoffset]; | ||
121 | } | ||
122 | else | ||
123 | { | ||
124 | val = key[keyoffset] | ||
125 | | (key[(keyoffset + 1) % keylen] << 8) | ||
126 | | (key[(keyoffset + 2) % keylen] << 16) | ||
127 | | (key[(keyoffset + 3) % keylen] << 24); | ||
128 | } | ||
129 | keys[i] = (val - 0x01010101) | 0x80808080; | ||
130 | } | ||
131 | |||
132 | // Determine the number of dwords in the buffer. | ||
133 | int len_div = len / sizeof(dword); | ||
134 | |||
135 | // Decrypt all dwords of the buffer. | ||
136 | for (int i = 0; i < len_div; i++) | ||
137 | { | ||
138 | ((dword*)buffer)[i] ^= keys[i % keyscount]; | ||
139 | } | ||
140 | |||
141 | // Determine the remaining number of bytes in the buffer. | ||
142 | int len_rem = len % sizeof(dword); | ||
143 | |||
144 | // Decrypt the remaining number of bytes in the buffer. | ||
145 | for (int i = len_div * sizeof(dword); i < len; i++) | ||
146 | { | ||
147 | buffer[i] ^= ((key[i % keylen] - 0x01) | 0x80); | ||
148 | } | ||
149 | |||
150 | return true; | ||
151 | } | ||
diff --git a/utils/zenutils/source/shared/updater.h b/utils/zenutils/source/shared/updater.h new file mode 100755 index 0000000000..57f9979c30 --- /dev/null +++ b/utils/zenutils/source/shared/updater.h | |||
@@ -0,0 +1,32 @@ | |||
1 | /* zenutils - Utilities for working with creative firmwares. | ||
2 | * Copyright 2007 (c) Rasmus Ry <rasmus.ry{at}gmail.com> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
17 | */ | ||
18 | |||
19 | #ifndef ZEN_UPDATER_H_INCLUDED | ||
20 | #define ZEN_UPDATER_H_INCLUDED | ||
21 | |||
22 | #include <pelib/PeLib.h> | ||
23 | #include <utils.h> | ||
24 | |||
25 | namespace zen { | ||
26 | const char* find_firmware_key(const byte* buffer, size_t len); | ||
27 | dword find_firmware_offset(byte* buffer, size_t len); | ||
28 | bool find_firmware_archive(const std::string& filename, dword& va, dword& pa); | ||
29 | bool crypt_firmware(const char* key, byte* buffer, size_t len); | ||
30 | }; //namespace zen | ||
31 | |||
32 | #endif //ZEN_UPDATER_H_INCLUDED | ||
diff --git a/utils/zenutils/source/shared/utils.cpp b/utils/zenutils/source/shared/utils.cpp new file mode 100755 index 0000000000..8f45de5d3f --- /dev/null +++ b/utils/zenutils/source/shared/utils.cpp | |||
@@ -0,0 +1,211 @@ | |||
1 | /* zenutils - Utilities for working with creative firmwares. | ||
2 | * Copyright 2007 (c) Rasmus Ry <rasmus.ry{at}gmail.com> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
17 | */ | ||
18 | |||
19 | #include "utils.h" | ||
20 | #include <fstream> | ||
21 | #include <zlib/zlib.h> | ||
22 | |||
23 | |||
24 | std::string shared::replace_extension(const std::string& filename, const std::string& extension) | ||
25 | { | ||
26 | std::string newname; | ||
27 | const char* name = filename.c_str(); | ||
28 | const char* ext = strrchr(name, '.'); | ||
29 | if (ext) | ||
30 | { | ||
31 | // If an extension was found, replace it. | ||
32 | newname.assign(name, ext-name); | ||
33 | newname += extension; | ||
34 | } | ||
35 | else | ||
36 | { | ||
37 | // If an extension was not found, append it. | ||
38 | newname = name; | ||
39 | newname += extension; | ||
40 | } | ||
41 | return newname; | ||
42 | } | ||
43 | |||
44 | std::string shared::remove_extension(const std::string& filename) | ||
45 | { | ||
46 | std::string newname; | ||
47 | const char* name = filename.c_str(); | ||
48 | const char* ext = strrchr(name, '.'); | ||
49 | if (ext) | ||
50 | { | ||
51 | newname.assign(name, ext-name); | ||
52 | } | ||
53 | else | ||
54 | { | ||
55 | newname = name; | ||
56 | } | ||
57 | return newname; | ||
58 | } | ||
59 | |||
60 | std::string shared::double_quote(const std::string& str) | ||
61 | { | ||
62 | std::string out; | ||
63 | for (int i = 0, j = str.length(); i < j; i++) | ||
64 | { | ||
65 | if (str[i] == '\\') | ||
66 | out += "\\\\"; | ||
67 | else | ||
68 | out += str[i]; | ||
69 | } | ||
70 | return out; | ||
71 | } | ||
72 | |||
73 | bool shared::inflate_to_file(const bytes& buffer, const char* filename) | ||
74 | { | ||
75 | // Open output file. | ||
76 | std::ofstream ofs; | ||
77 | ofs.open(filename, std::ios::binary); | ||
78 | if (!ofs) | ||
79 | { | ||
80 | return false; | ||
81 | } | ||
82 | |||
83 | // Initialize zlib. | ||
84 | z_stream d_stream; // decompression stream | ||
85 | |||
86 | d_stream.zalloc = Z_NULL; | ||
87 | d_stream.zfree = Z_NULL; | ||
88 | d_stream.opaque = Z_NULL; | ||
89 | |||
90 | d_stream.next_in = const_cast<bytes::value_type*>(&buffer[0]); | ||
91 | d_stream.avail_in = static_cast<uInt>(buffer.size()); | ||
92 | |||
93 | int ret = inflateInit(&d_stream); | ||
94 | if (ret != Z_OK) | ||
95 | return false; | ||
96 | |||
97 | // Allocate buffer to hold the inflated data. | ||
98 | const size_t BUFSIZE = 1048576; | ||
99 | Bytef* infbuf = new Bytef[BUFSIZE]; | ||
100 | if (!infbuf) | ||
101 | return false; | ||
102 | |||
103 | // Decompress untill the end of the input buffer. | ||
104 | uLong totalout = 0; | ||
105 | bool bLoop = true; | ||
106 | while (bLoop) | ||
107 | { | ||
108 | d_stream.next_out = infbuf; | ||
109 | d_stream.avail_out = BUFSIZE; | ||
110 | |||
111 | ret = inflate(&d_stream, Z_NO_FLUSH); | ||
112 | if (ret == Z_STREAM_END) | ||
113 | { | ||
114 | bLoop = false; | ||
115 | } | ||
116 | else if (ret != Z_OK) | ||
117 | { | ||
118 | inflateEnd(&d_stream); | ||
119 | delete [] infbuf; | ||
120 | return false; | ||
121 | } | ||
122 | |||
123 | // Write the inflated data to the output file. | ||
124 | if (!ofs.write((const char*)infbuf, d_stream.total_out-totalout)) | ||
125 | { | ||
126 | inflateEnd(&d_stream); | ||
127 | delete [] infbuf; | ||
128 | return false; | ||
129 | } | ||
130 | totalout = d_stream.total_out; | ||
131 | } | ||
132 | |||
133 | // Cleanup and return. | ||
134 | inflateEnd(&d_stream); | ||
135 | delete [] infbuf; | ||
136 | |||
137 | return true; | ||
138 | } | ||
139 | |||
140 | bool shared::deflate_to_file(const bytes& buffer, const char* filename) | ||
141 | { | ||
142 | // Open output file. | ||
143 | std::ofstream ofs; | ||
144 | ofs.open(filename, std::ios::binary); | ||
145 | if (!ofs) | ||
146 | { | ||
147 | return false; | ||
148 | } | ||
149 | |||
150 | // Initialize zlib. | ||
151 | z_stream c_stream; // compression stream. | ||
152 | |||
153 | c_stream.zalloc = Z_NULL; | ||
154 | c_stream.zfree = Z_NULL; | ||
155 | c_stream.opaque = Z_NULL; | ||
156 | |||
157 | int ret = deflateInit(&c_stream, Z_BEST_COMPRESSION); | ||
158 | if (ret != Z_OK) | ||
159 | return false; | ||
160 | |||
161 | // Allocate buffer to hold the deflated data. | ||
162 | const size_t BUFSIZE = 1048576; | ||
163 | Bytef* defbuf = new Bytef[BUFSIZE]; | ||
164 | if (!defbuf) | ||
165 | return false; | ||
166 | |||
167 | c_stream.avail_in = static_cast<uInt>(buffer.size()); | ||
168 | c_stream.next_in = const_cast<bytes::value_type*>(&buffer[0]); | ||
169 | |||
170 | // Compress until end of the buffer. | ||
171 | uLong totalout = 0; | ||
172 | bool bLoop = true; | ||
173 | while (bLoop) | ||
174 | { | ||
175 | c_stream.avail_out = BUFSIZE; | ||
176 | c_stream.next_out = defbuf; | ||
177 | |||
178 | ret = deflate(&c_stream, Z_NO_FLUSH); // no bad return value | ||
179 | if (ret == Z_STREAM_END) | ||
180 | { | ||
181 | bLoop = false; | ||
182 | } | ||
183 | else if (ret == Z_BUF_ERROR && !c_stream.avail_in) | ||
184 | { | ||
185 | ret = deflate(&c_stream, Z_FINISH); // no bad return value | ||
186 | bLoop = false; | ||
187 | } | ||
188 | else if (ret != Z_OK) | ||
189 | { | ||
190 | deflateEnd(&c_stream); | ||
191 | delete [] defbuf; | ||
192 | return false; | ||
193 | } | ||
194 | |||
195 | // Write the inflated data to the output file. | ||
196 | if (!ofs.write((const char*)defbuf, c_stream.total_out-totalout)) | ||
197 | { | ||
198 | deflateEnd(&c_stream); | ||
199 | delete [] defbuf; | ||
200 | return false; | ||
201 | } | ||
202 | |||
203 | totalout = c_stream.total_out; | ||
204 | } | ||
205 | |||
206 | // Clean up and return. | ||
207 | deflateEnd(&c_stream); | ||
208 | delete [] defbuf; | ||
209 | |||
210 | return true; | ||
211 | } | ||
diff --git a/utils/zenutils/source/shared/utils.h b/utils/zenutils/source/shared/utils.h new file mode 100755 index 0000000000..ca9e291514 --- /dev/null +++ b/utils/zenutils/source/shared/utils.h | |||
@@ -0,0 +1,68 @@ | |||
1 | /* zenutils - Utilities for working with creative firmwares. | ||
2 | * Copyright 2007 (c) Rasmus Ry <rasmus.ry{at}gmail.com> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
17 | */ | ||
18 | |||
19 | #ifndef SHARED_UTILS_H_INCLUDED | ||
20 | #define SHARED_UTILS_H_INCLUDED | ||
21 | |||
22 | #include <vector> | ||
23 | #include <pelib/PeLib.h> | ||
24 | |||
25 | #ifndef byte | ||
26 | typedef PeLib::byte byte; | ||
27 | #endif | ||
28 | #ifndef word | ||
29 | typedef PeLib::word word; | ||
30 | #endif | ||
31 | #ifndef dword | ||
32 | typedef PeLib::dword dword; | ||
33 | #endif | ||
34 | |||
35 | namespace shared { | ||
36 | typedef std::vector<byte> bytes; | ||
37 | |||
38 | inline dword swap(dword val) | ||
39 | { | ||
40 | return ((val & 0xFF) << 24) | ||
41 | | ((val & 0xFF00) << 8) | ||
42 | | ((val & 0xFF0000) >> 8) | ||
43 | | ((val & 0xFF000000) >> 24); | ||
44 | } | ||
45 | |||
46 | template <typename _Type> | ||
47 | inline void reverse(_Type* start, _Type* end) | ||
48 | { | ||
49 | while (start < end) | ||
50 | { | ||
51 | *start ^= *end; | ||
52 | *end ^= *start; | ||
53 | *start ^= *end; | ||
54 | start++; | ||
55 | end--; | ||
56 | } | ||
57 | } | ||
58 | |||
59 | std::string replace_extension(const std::string& filename, const std::string& extension); | ||
60 | std::string remove_extension(const std::string& filename); | ||
61 | std::string get_path(const std::string& filename); | ||
62 | std::string double_quote(const std::string& str); | ||
63 | |||
64 | bool inflate_to_file(const bytes& buffer, const char* filename); | ||
65 | bool deflate_to_file(const bytes& buffer, const char* filename); | ||
66 | }; //namespace shared | ||
67 | |||
68 | #endif //SHARED_UTILS_H_INCLUDED | ||