1 /* zenutils - Utilities for working with creative firmwares.
2 * Copyright 2007 (c) Rasmus Ry <rasmus.ry{at}gmail.com>
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.
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.
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
22 #include <getpot/GetPot>
28 static const char VERSION
[] = "0.1";
33 << "update_extract - Extracts a Creative firmware from an updater"
34 " executable." << std::endl
35 << "Version " << VERSION
<< std::endl
36 << "Copyright (c) 2007 Rasmus Ry" << std::endl
;
42 std::cout
<< std::endl
43 << "Usage: update_extract [command] [options]" << std::endl
45 << " Commands:" << std::endl
46 << " -h,--help" << std::endl
47 << " prints this message." << std::endl
48 << " -u,--updater [file]" << std::endl
49 << " specifies the updater executable." << std::endl
51 << " Options:" << std::endl
52 << " -V,--verbose" << std::endl
53 << " prints verbose messages." << std::endl
54 << " -f,--firmware [file]" << std::endl
55 << " specifies the firmware arhive file name." << std::endl
56 << " -k,--key [key]" << std::endl
57 << " specifies the firmware archive key." << std::endl
58 << " -o,--offset [offset]" << std::endl
59 << " specifies the firmware archive offset in c-style"
60 " hexadecimal." << std::endl
65 std::string
options_name(const std::string
& name
)
67 return shared::replace_extension(name
, ".opt");
70 std::string
default_firmware_name(const std::string
& name
)
72 return shared::replace_extension(name
, "_rk.bin");
75 int process_arguments(int argc
, char* argv
[])
77 //--------------------------------------------------------------------
78 // Parse input variables.
79 //--------------------------------------------------------------------
81 GetPot
cl(argc
, argv
);
82 if (cl
.size() == 1 || cl
.search(2, "-h", "--help"))
88 std::string updatername
;
89 if (cl
.search("-u") || cl
.search("--updater"))
90 updatername
= cl
.next("");
91 if (updatername
.empty())
93 std::cerr
<< "Updater executable must be specified." << std::endl
;
97 std::string firmarename
= default_firmware_name(updatername
);
98 if (cl
.search("-f") || cl
.search("--firmware"))
99 firmarename
= cl
.next(firmarename
.c_str());
101 bool verbose
= false;
102 if (cl
.search("-V") || cl
.search("--verbose"))
105 // Get or find the firmware archive key.
107 if (cl
.search("-k") || cl
.search("--key"))
113 std::cout
<< "[*] Looking for firmware archive key..."
115 shared::bytes buffer
;
116 if (!shared::read_file(updatername
, buffer
))
118 std::cerr
<< "Failed to read the firmware updater executable."
122 key
= zen::find_firmware_key(&buffer
[0], buffer
.size());
125 std::cerr
<< "Failed to find the firmware archive key."
131 // Get or find the firmware archive offset.
134 if (cl
.search("-o") || cl
.search("--ofset"))
135 offset
= cl
.next("");
140 std::cout
<< "[*] Looking for firmware archive offset..."
144 if (!zen::find_firmware_archive(updatername
, offset_va
, offset_pa
))
146 std::cerr
<< "Failed to find the firmware archive offset."
154 if (!sscanf(offset
.c_str(), "0x%x", &offset_val
))
156 if (!sscanf(offset
.c_str(), "0x%X", &offset_val
))
158 std::cerr
<< "\'" << offset
159 << "\' is not a valid c-style hexadecimal value."
164 offset_pa
= static_cast<dword
>(offset_val
);
167 // Read firmware archive size.
168 shared::bytes buffer
;
169 if (!shared::read_file(updatername
, buffer
, offset_pa
, sizeof(dword
)))
171 std::cerr
<< "Failed to read the firmware archive size." << std::endl
;
174 dword archive_size
= *(dword
*)&buffer
[0];
178 std::cout
<< "[*] Printing input variables..." << std::endl
;
179 std::cout
<< " Updater executable: " << updatername
<< std::endl
;
180 std::cout
<< " Firmware archive: " << firmarename
<< std::endl
;
181 std::cout
<< " Key: " << key
<< std::endl
;
182 std::cout
<< " Offset: "
183 << std::hex
<< std::showbase
<< std::setw(10)
184 << std::setfill('0') << std::internal
185 << offset_pa
<< std::endl
;
186 std::cout
<< " Size: "
187 << std::hex
<< std::showbase
<< std::setw(10)
188 << std::setfill('0') << std::internal
189 << archive_size
<< std::endl
;
193 //--------------------------------------------------------------------
194 // Extract the firmware archive from the updater.
195 //--------------------------------------------------------------------
198 std::cout
<< "[*] Reading firmware archive..." << std::endl
;
200 // Read the firmware archive.
201 offset_pa
+= sizeof(dword
);
202 if (!shared::read_file(updatername
, buffer
, offset_pa
, archive_size
))
204 std::cerr
<< "Failed to read the firmware archive." << std::endl
;
209 std::cout
<< "[*] Decrypting firmware archive..." << std::endl
;
211 // Decrypt the firmware archive.
212 if (!zen::crypt_firmware(key
.c_str(), &buffer
[0], buffer
.size()))
214 std::cerr
<< "Failed to decrypt the firmware archive." << std::endl
;
219 std::cout
<< "[*] Decompressing firmware archive..." << std::endl
;
221 // Inflate the firmware archive to the output file.
222 if (!shared::inflate_to_file(buffer
, firmarename
.c_str()))
224 std::cerr
<< "Failed to decompress the firmware archive." << std::endl
;
229 //--------------------------------------------------------------------
230 // Generate an options file for the extracted firmware archive.
231 //--------------------------------------------------------------------
233 // Get options filename for the given input file.
234 std::string optionsname
= options_name(updatername
);
237 std::cout
<< "[*] Producing options file..." << std::endl
;
239 // Produce options file for the given input file.
241 ofs
.open(optionsname
.c_str(), std::ios::binary
);
244 std::cerr
<< "Failed to create firmware archive options file."
249 time_t timeval
= time(NULL
);
250 ofs
<< "# Options file generated at: " << ctime(&timeval
)
251 << "updater = \'" << shared::double_quote(updatername
) << "\'"
253 << "firmware = \'" << shared::double_quote(firmarename
) << "\'"
255 << "offset = " << (offset_pa
- sizeof(dword
)) << std::endl
256 << "size = " << archive_size
<< std::endl
257 << "key = \'" << key
<< "\'" << std::endl
;
262 int main(int argc
, char* argv
[])
266 return process_arguments(argc
, argv
);
268 catch (const std::exception
& xcpt
)
270 std::cerr
<< "Exception caught: " << xcpt
.what() << std::endl
;
275 std::cerr
<< "Unknown exception caught." << std::endl
;