Make the greylib text output functions handle unicode. Fixes non-working umlauts...
[kugel-rb.git] / rbutil / rbutilqt / base / bootloaderinstallhex.cpp
blobaa42beb994c3e8e8d0c4a94534dba2a41f5a402a
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
9 * Copyright (C) 2008 by Dominik Riebeling
10 * $Id$
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.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
20 #include <QtCore>
21 #include "bootloaderinstallbase.h"
22 #include "bootloaderinstallhex.h"
24 #include "../../tools/iriver.h"
25 #include "../../tools/mkboot.h"
27 struct md5s {
28 const char* orig;
29 const char* patched;
32 struct 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 }
42 BootloaderInstallHex::BootloaderInstallHex(QObject *parent)
43 : BootloaderInstallBase(parent)
48 bool BootloaderInstallHex::install(void)
50 if(m_hex.isEmpty())
51 return false;
52 m_hashindex = -1;
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;
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;
80 if(i < 0) {
81 emit logItem(tr("Firmware file not recognized."), LOGERROR);
82 return false;
84 else {
85 emit logItem(tr("MD5 hash ok"), LOGOK);
86 m_hashindex = i;
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;
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;
104 if(result < 0) {
105 emit logItem(tr("Error in descramble: %1").arg(scrambleError(result)), LOGERROR);
106 return false;
109 // download firmware from server
110 emit logItem(tr("Downloading bootloader file"), LOGINFO);
111 connect(this, SIGNAL(downloadDone()), this, SLOT(installStage2()));
113 downloadBlStart(m_blurl);
114 return true;
118 void BootloaderInstallHex::installStage2(void)
120 emit logItem(tr("Adding bootloader to firmware file"), LOGINFO);
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();
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;
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)
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;
165 emit logItem(tr("Error in patching: %1").arg(error), LOGERROR);
167 emit done(true);
168 return;
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)
176 emit logItem(tr("Error in scramble: %1").arg(scrambleError(result)), LOGERROR);
177 targethex.close();
179 emit done(true);
180 return;
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;
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;
198 // finally copy file to player
199 targethex.copy(m_blfile);
201 emit logItem(tr("Success: modified firmware file created"), LOGINFO);
202 logInstall(LogAdd);
203 emit done(false);
205 return;
209 bool BootloaderInstallHex::uninstall(void)
211 emit logItem("Uninstallation not possible, only installation info removed", LOGINFO);
212 logInstall(LogRemove);
213 return false;
217 BootloaderInstallBase::BootloaderType BootloaderInstallHex::installed(void)
219 return BootloaderUnknown;
223 BootloaderInstallBase::Capabilities BootloaderInstallHex::capabilities(void)
225 return (Install | NeedsFlashing);
228 QString BootloaderInstallHex::scrambleError(int err)
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;
242 return error;