diff options
author | Dominik Riebeling <Dominik.Riebeling@gmail.com> | 2008-09-28 17:02:36 +0000 |
---|---|---|
committer | Dominik Riebeling <Dominik.Riebeling@gmail.com> | 2008-09-28 17:02:36 +0000 |
commit | 197c24c5d331703b8b1d743f5699263cd623df38 (patch) | |
tree | 9c054f54f43b0c788b0760adf08595fe48643afb /rbutil/rbutilqt/bootloaderinstallhex.cpp | |
parent | 063d37b08f6110a250c1f1a70883c4c45705f7b8 (diff) | |
download | rockbox-197c24c5d331703b8b1d743f5699263cd623df38.tar.gz rockbox-197c24c5d331703b8b1d743f5699263cd623df38.zip |
Completely rework the bootloader installation class:
- create a base class and make derived classes for each installation type.
- sort installations by type, not by player model.
- remove duplicated code for iriver (de)scrambling functionality and use the functions inside of the tools folder directly -- we already do the same for rbspeex.
- make bootloader file backup optional and allow choosing a target location.
- clean up some wording and add some more guiding messages.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@18657 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'rbutil/rbutilqt/bootloaderinstallhex.cpp')
-rw-r--r-- | rbutil/rbutilqt/bootloaderinstallhex.cpp | 244 |
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 | |||
27 | struct md5s { | ||
28 | const char* orig; | ||
29 | const char* patched; | ||
30 | }; | ||
31 | |||
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 } | ||
39 | }; | ||
40 | |||
41 | |||
42 | BootloaderInstallHex::BootloaderInstallHex(QObject *parent) | ||
43 | : BootloaderInstallBase(parent) | ||
44 | { | ||
45 | } | ||
46 | |||
47 | |||
48 | bool 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 | |||
118 | void 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 | |||
209 | bool BootloaderInstallHex::uninstall(void) | ||
210 | { | ||
211 | emit logItem("Uninstallation not possible, only installation info removed", LOGINFO); | ||
212 | logInstall(LogRemove); | ||
213 | return false; | ||
214 | } | ||
215 | |||
216 | |||
217 | BootloaderInstallBase::BootloaderType BootloaderInstallHex::installed(void) | ||
218 | { | ||
219 | return BootloaderUnknown; | ||
220 | } | ||
221 | |||
222 | |||
223 | BootloaderInstallBase::Capabilities BootloaderInstallHex::capabilities(void) | ||
224 | { | ||
225 | return (Install | NeedsFlashing); | ||
226 | } | ||
227 | |||
228 | QString 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 | |||