1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
9 * Copyright (C) 2008 by Dominik Riebeling
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 ****************************************************************************/
21 #include "bootloaderinstallbase.h"
22 #include "bootloaderinstallhex.h"
24 #include "../../tools/iriver.h"
25 #include "../../tools/mkboot.h"
32 struct md5s md5sums
[] = {
33 #include "irivertools/h100sums.h"
35 #include "irivertools/h120sums.h"
37 #include "irivertools/h300sums.h"
42 BootloaderInstallHex::BootloaderInstallHex(QObject
*parent
)
43 : BootloaderInstallBase(parent
)
47 QString
BootloaderInstallHex::ofHint()
49 return tr("Bootloader installation requires you to provide "
50 "a firmware file of the original firmware (hex file). "
51 "You need to download this file yourself due to legal "
52 "reasons. Please refer to the "
53 "<a href='http://www.rockbox.org/manual.shtml'>manual</a> and the "
54 "<a href='http://www.rockbox.org/wiki/IriverBoot"
55 "#Download_and_extract_a_recent_ve'>IriverBoot</a> wiki page on "
56 "how to obtain this file.<br/>"
57 "Press Ok to continue and browse your computer for the firmware "
61 bool BootloaderInstallHex::install(void)
63 if(m_offile
.isEmpty())
68 emit
logItem(tr("checking MD5 hash of input file ..."), LOGINFO
);
70 // read hex file into QByteArray
72 file
.open(QIODevice::ReadOnly
);
73 filedata
= file
.readAll();
75 QString hash
= QCryptographicHash::hash(filedata
,
76 QCryptographicHash::Md5
).toHex();
77 qDebug() << "[BootloaderInstallHex] hexfile hash:" << hash
;
78 if(file
.error() != QFile::NoError
) {
79 emit
logItem(tr("Could not verify original firmware file"), LOGERROR
);
83 // check hash and figure model from md5sum
84 int i
= sizeof(md5sums
) / sizeof(struct md5s
);
86 // 3: h300, 2: h120, 1: h100, 0:invalid
88 if(md5sums
[i
].orig
== 0)
90 if(!qstrcmp(md5sums
[i
].orig
, hash
.toAscii()))
94 emit
logItem(tr("Firmware file not recognized."), LOGERROR
);
98 emit
logItem(tr("MD5 hash ok"), LOGOK
);
102 // check model agains download link.
103 QString match
[] = {"", "h100", "h120", "h300"};
104 if(!m_blurl
.path().contains(match
[m_model
])) {
105 emit
logItem(tr("Firmware file doesn't match selected player."),
110 emit
logItem(tr("Descrambling file"), LOGINFO
);
111 m_descrambled
.open();
113 result
= iriver_decode(m_offile
.toAscii().data(),
114 m_descrambled
.fileName().toAscii().data(), FALSE
, STRIP_NONE
);
115 qDebug() << "[BootloaderInstallHex] iriver_decode" << result
;
118 emit
logItem(tr("Error in descramble: %1").arg(scrambleError(result
)), LOGERROR
);
122 // download firmware from server
123 emit
logItem(tr("Downloading bootloader file"), LOGINFO
);
124 connect(this, SIGNAL(downloadDone()), this, SLOT(installStage2()));
126 downloadBlStart(m_blurl
);
131 void BootloaderInstallHex::installStage2(void)
133 emit
logItem(tr("Adding bootloader to firmware file"), LOGINFO
);
134 QCoreApplication::processEvents();
137 QTemporaryFile tempbin
;
139 QString tempbinName
= tempbin
.fileName();
141 // get temporary files filenames -- external tools need this.
142 m_descrambled
.open();
143 QString descrambledName
= m_descrambled
.fileName();
144 m_descrambled
.close();
146 QString tempfileName
= m_tempfile
.fileName();
163 // iriver decode already done in stage 1
165 if((result
= mkboot(descrambledName
.toLocal8Bit().constData(),
166 tempfileName
.toLocal8Bit().constData(),
167 tempbinName
.toLocal8Bit().constData(), origin
)) < 0)
171 case -1: error
= tr("could not open input file"); break;
172 case -2: error
= tr("reading header failed"); break;
173 case -3: error
= tr("reading firmware failed"); break;
174 case -4: error
= tr("can't open bootloader file"); break;
175 case -5: error
= tr("reading bootloader file failed"); break;
176 case -6: error
= tr("can't open output file"); break;
177 case -7: error
= tr("writing output file failed"); break;
179 emit
logItem(tr("Error in patching: %1").arg(error
), LOGERROR
);
184 QTemporaryFile targethex
;
186 QString targethexName
= targethex
.fileName();
187 if((result
= iriver_encode(tempbinName
.toLocal8Bit().constData(),
188 targethexName
.toLocal8Bit().constData(), FALSE
)) < 0)
190 emit
logItem(tr("Error in scramble: %1").arg(scrambleError(result
)), LOGERROR
);
197 // finally check the md5sum of the created file
199 filedata
= targethex
.readAll();
201 QString hash
= QCryptographicHash::hash(filedata
,
202 QCryptographicHash::Md5
).toHex();
203 qDebug() << "[BootloaderInstallHex] created hexfile hash:" << hash
;
205 emit
logItem(tr("Checking modified firmware file"), LOGINFO
);
206 if(hash
!= QString(md5sums
[m_hashindex
].patched
)) {
207 emit
logItem(tr("Error: modified file checksum wrong"), LOGERROR
);
212 // finally copy file to player
213 targethex
.copy(m_blfile
);
215 emit
logItem(tr("Success: modified firmware file created"), LOGINFO
);
223 bool BootloaderInstallHex::uninstall(void)
225 emit
logItem(tr("Uninstallation not possible, only installation info removed"), LOGINFO
);
226 logInstall(LogRemove
);
231 BootloaderInstallBase::BootloaderType
BootloaderInstallHex::installed(void)
233 return BootloaderUnknown
;
237 BootloaderInstallBase::Capabilities
BootloaderInstallHex::capabilities(void)
239 return (Install
| NeedsOf
);
242 QString
BootloaderInstallHex::scrambleError(int err
)
246 case -1: error
= tr("Can't open input file"); break;
247 case -2: error
= tr("Can't open output file"); break;
248 case -3: error
= tr("invalid file: header length wrong"); break;
249 case -4: error
= tr("invalid file: unrecognized header"); break;
250 case -5: error
= tr("invalid file: \"length\" field wrong"); break;
251 case -6: error
= tr("invalid file: \"length2\" field wrong"); break;
252 case -7: error
= tr("invalid file: internal checksum error"); break;
253 case -8: error
= tr("invalid file: \"length3\" field wrong"); break;
254 default: error
= tr("unknown"); break;