summaryrefslogtreecommitdiff
path: root/rbutil/rbutilqt/bootloaderinstallhex.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'rbutil/rbutilqt/bootloaderinstallhex.cpp')
-rw-r--r--rbutil/rbutilqt/bootloaderinstallhex.cpp244
1 files changed, 244 insertions, 0 deletions
diff --git a/rbutil/rbutilqt/bootloaderinstallhex.cpp b/rbutil/rbutilqt/bootloaderinstallhex.cpp
new file mode 100644
index 0000000000..e4cc4cc08a
--- /dev/null
+++ b/rbutil/rbutilqt/bootloaderinstallhex.cpp
@@ -0,0 +1,244 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 *
9 * Copyright (C) 2008 by Dominik Riebeling
10 * $Id:$
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#include <QtCore>
21#include "bootloaderinstallbase.h"
22#include "bootloaderinstallhex.h"
23
24#include "../../tools/iriver.h"
25#include "../../tools/mkboot.h"
26
27struct md5s {
28 const char* orig;
29 const char* patched;
30};
31
32struct md5s md5sums[] = {
33#include "irivertools/h100sums.h"
34 { 0, 0 },
35#include "irivertools/h120sums.h"
36 { 0, 0 },
37#include "irivertools/h300sums.h"
38 { 0, 0 }
39};
40
41
42BootloaderInstallHex::BootloaderInstallHex(QObject *parent)
43 : BootloaderInstallBase(parent)
44{
45}
46
47
48bool BootloaderInstallHex::install(void)
49{
50 if(m_hex.isEmpty())
51 return false;
52 m_hashindex = -1;
53
54 // md5sum hex file
55 emit logItem(tr("checking MD5 hash of input file ..."), LOGINFO);
56 QByteArray filedata;
57 // read hex file into QByteArray
58 QFile file(m_hex);
59 file.open(QIODevice::ReadOnly);
60 filedata = file.readAll();
61 file.close();
62 QString hash = QCryptographicHash::hash(filedata,
63 QCryptographicHash::Md5).toHex();
64 qDebug() << "hexfile hash:" << hash;
65 if(file.error() != QFile::NoError) {
66 emit logItem(tr("Could not verify original firmware file"), LOGERROR);
67 emit done(true);
68 return false;
69 }
70 // check hash and figure model from md5sum
71 int i = sizeof(md5sums) / sizeof(struct md5s);
72 m_model = 4;
73 // 3: h300, 2: h120, 1: h100, 0:invalid
74 while(i--) {
75 if(md5sums[i].orig == 0)
76 m_model--;
77 if(!qstrcmp(md5sums[i].orig, hash.toAscii()))
78 break;
79 }
80 if(i < 0) {
81 emit logItem(tr("Firmware file not recognized."), LOGERROR);
82 return false;
83 }
84 else {
85 emit logItem(tr("MD5 hash ok"), LOGOK);
86 m_hashindex = i;
87 }
88
89 // check model agains download link.
90 QString match[] = {"", "h100", "h120", "h300"};
91 if(!m_blurl.path().contains(match[m_model])) {
92 emit logItem(tr("Firmware file doesn't match selected player."),
93 LOGERROR);
94 return false;
95 }
96
97 emit logItem(tr("Descrambling file"), LOGINFO);
98 m_descrambled.open();
99 int result;
100 result = iriver_decode(m_hex.toAscii().data(),
101 m_descrambled.fileName().toAscii().data(), FALSE, STRIP_NONE);
102 qDebug() << "iriver_decode" << result;
103
104 if(result < 0) {
105 emit logItem(tr("Error in descramble: %1").arg(scrambleError(result)), LOGERROR);
106 return false;
107 }
108
109 // download firmware from server
110 emit logItem(tr("Downloading bootloader file"), LOGINFO);
111 connect(this, SIGNAL(downloadDone()), this, SLOT(installStage2()));
112
113 downloadBlStart(m_blurl);
114 return true;
115}
116
117
118void BootloaderInstallHex::installStage2(void)
119{
120 emit logItem(tr("Adding bootloader to firmware file"), LOGINFO);
121
122 // local temp file
123 QTemporaryFile tempbin;
124 tempbin.open();
125 QString tempbinName = tempbin.fileName();
126 tempbin.close();
127 // get temporary files filenames -- external tools need this.
128 m_descrambled.open();
129 QString descrambledName = m_descrambled.fileName();
130 m_descrambled.close();
131 m_tempfile.open();
132 QString tempfileName = m_tempfile.fileName();
133 m_tempfile.close();
134
135 int origin = 0;
136 switch(m_model) {
137 case 3:
138 origin = 0x3f0000;
139 break;
140 case 2:
141 case 1:
142 origin = 0x1f0000;
143 break;
144 default:
145 origin = 0;
146 break;
147 }
148
149 // iriver decode already done in stage 1
150 int result;
151 if((result = mkboot(descrambledName.toLocal8Bit().constData(),
152 tempfileName.toLocal8Bit().constData(),
153 tempbinName.toLocal8Bit().constData(), origin)) < 0)
154 {
155 QString error;
156 switch(result) {
157 case -1: error = tr("could not open input file"); break;
158 case -2: error = tr("reading header failed"); break;
159 case -3: error = tr("reading firmware failed"); break;
160 case -4: error = tr("can't open bootloader file"); break;
161 case -5: error = tr("reading bootloader file failed"); break;
162 case -6: error = tr("can't open output file"); break;
163 case -7: error = tr("writing output file failed"); break;
164 }
165 emit logItem(tr("Error in patching: %1").arg(error), LOGERROR);
166
167 emit done(true);
168 return;
169 }
170 QTemporaryFile targethex;
171 targethex.open();
172 QString targethexName = targethex.fileName();
173 if((result = iriver_encode(tempbinName.toLocal8Bit().constData(),
174 targethexName.toLocal8Bit().constData(), FALSE)) < 0)
175 {
176 emit logItem(tr("Error in scramble: %1").arg(scrambleError(result)), LOGERROR);
177 targethex.close();
178
179 emit done(true);
180 return;
181 }
182
183 // finally check the md5sum of the created file
184 QByteArray filedata;
185 filedata = targethex.readAll();
186 targethex.close();
187 QString hash = QCryptographicHash::hash(filedata,
188 QCryptographicHash::Md5).toHex();
189 qDebug() << "created hexfile hash:" << hash;
190
191 emit logItem(tr("Checking modified firmware file"), LOGINFO);
192 if(hash != QString(md5sums[m_hashindex].patched)) {
193 emit logItem(tr("Error: modified file checksum wrong"), LOGERROR);
194 targethex.remove();
195 emit done(true);
196 return;
197 }
198 // finally copy file to player
199 targethex.copy(m_blfile);
200
201 emit logItem(tr("Success: modified firmware file created"), LOGINFO);
202 logInstall(LogAdd);
203 emit done(false);
204
205 return;
206}
207
208
209bool BootloaderInstallHex::uninstall(void)
210{
211 emit logItem("Uninstallation not possible, only installation info removed", LOGINFO);
212 logInstall(LogRemove);
213 return false;
214}
215
216
217BootloaderInstallBase::BootloaderType BootloaderInstallHex::installed(void)
218{
219 return BootloaderUnknown;
220}
221
222
223BootloaderInstallBase::Capabilities BootloaderInstallHex::capabilities(void)
224{
225 return (Install | NeedsFlashing);
226}
227
228QString BootloaderInstallHex::scrambleError(int err)
229{
230 QString error;
231 switch(err) {
232 case -1: error = tr("Can't open input file"); break;
233 case -2: error = tr("Can't open output file"); break;
234 case -3: error = tr("invalid file: header length wrong"); break;
235 case -4: error = tr("invalid file: unrecognized header"); break;
236 case -5: error = tr("invalid file: \"length\" field wrong"); break;
237 case -6: error = tr("invalid file: \"length2\" field wrong"); break;
238 case -7: error = tr("invalid file: internal checksum error"); break;
239 case -8: error = tr("invalid file: \"length3\" field wrong"); break;
240 default: error = tr("unknown"); break;
241 }
242 return error;
243}
244