summaryrefslogtreecommitdiff
path: root/utils/zenutils/source/shared
diff options
context:
space:
mode:
Diffstat (limited to 'utils/zenutils/source/shared')
-rwxr-xr-xutils/zenutils/source/shared/CMakeLists.txt16
-rwxr-xr-xutils/zenutils/source/shared/cenc.cpp333
-rwxr-xr-xutils/zenutils/source/shared/cenc.h29
-rwxr-xr-xutils/zenutils/source/shared/crypt.cpp91
-rwxr-xr-xutils/zenutils/source/shared/crypt.h30
-rwxr-xr-xutils/zenutils/source/shared/file.cpp106
-rwxr-xr-xutils/zenutils/source/shared/file.h36
-rwxr-xr-xutils/zenutils/source/shared/firmware.cpp387
-rwxr-xr-xutils/zenutils/source/shared/firmware.h92
-rwxr-xr-xutils/zenutils/source/shared/pe.cpp128
-rwxr-xr-xutils/zenutils/source/shared/pe.h142
-rwxr-xr-xutils/zenutils/source/shared/shared.cpp0
-rwxr-xr-xutils/zenutils/source/shared/updater.cpp151
-rwxr-xr-xutils/zenutils/source/shared/updater.h32
-rwxr-xr-xutils/zenutils/source/shared/utils.cpp211
-rwxr-xr-xutils/zenutils/source/shared/utils.h68
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 @@
1PROJECT(shared)
2
3# source files for shared
4SET(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
14ADD_LIBRARY(shared ${shared_srcs})
15TARGET_LINK_LIBRARIES(shared pelib)
16TARGET_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
24namespace {
25const byte CODE_MASK = 0xC0;
26const byte ARGS_MASK = 0x3F;
27
28const byte REPEAT_CODE = 0x00;
29const byte BLOCK_CODE = 0x40;
30const byte LONG_RUN_CODE = 0x80;
31const byte SHORT_RUN_CODE = 0xC0;
32
33const byte BLOCK_ARGS = 0x1F;
34const byte BLOCK_MODE = 0x20;
35
36
37void decode_run(byte* dst, word len, byte val,
38 int& dstidx)
39{
40 memset(dst + dstidx, val, len);
41 dstidx += len;
42}
43
44void 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
69int 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
139namespace {
140int 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
219int 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
288int 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
24namespace 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
26bool 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(&param, key, keylen * 8))
31 return false;
32 if (hmacsha1Update(&param, data, datalen))
33 return false;
34 if (hmacsha1Digest(&param, sig))
35 return false;
36 return true;
37}
38
39bool 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(&param, key, keylen * 8, ENCRYPT))
48 return false;
49 if (blowfishSetIV(&param, 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, &param, (uint32_t*)data, (uint32_t*)plain,
57 nblocks))
58 {
59 delete [] plain;
60 return false;
61 }
62
63 return true;
64}
65
66bool 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(&param, key, keylen * 8, ENCRYPT))
75 return false;
76 if (blowfishSetIV(&param, 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, &param, (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
24namespace 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
23bool 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
51bool 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
79bool 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
91bool 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
99bool 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
26namespace 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
24zen::firmware_entry::firmware_entry(bool big_endian)
25 : _big_endian(big_endian)
26{
27}
28
29zen::firmware_entry::firmware_entry(const firmware_entry& copy)
30{
31 assign(copy);
32}
33
34zen::firmware_entry& zen::firmware_entry::operator=(const firmware_entry& right)
35{
36 assign(right);
37 return *this;
38}
39
40
41bool 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
68bool 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
99bool zen::firmware_entry::is_big_endian() const
100{
101 return _big_endian;
102}
103
104const zen::firmware_header_t& zen::firmware_entry::get_header() const
105{
106 return _header;
107}
108zen::firmware_header_t& zen::firmware_entry::get_header()
109{
110 return _header;
111}
112
113const shared::bytes& zen::firmware_entry::get_bytes() const
114{
115 return _bytes;
116}
117shared::bytes& zen::firmware_entry::get_bytes()
118{
119 return _bytes;
120}
121
122
123std::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
152std::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
182size_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
196size_t zen::firmware_entry::calc_size() const
197{
198 return _bytes.size() + sizeof(firmware_header_t);
199}
200
201
202void 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
212zen::firmware_archive::firmware_archive(bool big_endian)
213 : _big_endian(big_endian)
214{
215}
216
217zen::firmware_archive::firmware_archive(const firmware_archive& copy)
218{
219 assign(copy);
220}
221
222zen::firmware_archive& zen::firmware_archive::operator=(const firmware_archive& right)
223{
224 assign(right);
225 return *this;
226}
227
228
229bool 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
284bool 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
328bool zen::firmware_archive::is_big_endian() const
329{
330 return _big_endian;
331}
332
333const zen::firmware_entries& zen::firmware_archive::get_children() const
334{
335 return _children;
336}
337zen::firmware_entries& zen::firmware_archive::get_children()
338{
339 return _children;
340}
341
342const zen::firmware_entries& zen::firmware_archive::get_neighbours() const
343{
344 return _neighbours;
345}
346zen::firmware_entries& zen::firmware_archive::get_neighbours()
347{
348 return _neighbours;
349}
350
351bool 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
362size_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
382void 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
25namespace 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
22shared::pe_file::pe_file(PeLib::PeFile* pef) : _pef(pef)
23{
24}
25shared::pe_file::~pe_file()
26{
27 if (_pef != NULL)
28 delete _pef;
29}
30
31bool 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
50bool 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
86bool 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
97bool 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
113dword 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}
121dword 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
26namespace 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
25const 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
51dword 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
70bool 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
100bool 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
25namespace 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
24std::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
44std::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
60std::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
73bool 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
140bool 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
26typedef PeLib::byte byte;
27#endif
28#ifndef word
29typedef PeLib::word word;
30#endif
31#ifndef dword
32typedef PeLib::dword dword;
33#endif
34
35namespace 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