Rockbox Utility: add support for mkimxboot bootloader.
[maemo-rb.git] / rbutil / rbutilqt / base / bootloaderinstallbase.cpp
blob750e33bef8022b93aa374c5d8ff7533cb882fd54
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
9 * Copyright (C) 2008 by Dominik Riebeling
11 * All files in this archive are subject to the GNU General Public License.
12 * See the file COPYING in the source tree root for full license agreement.
14 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
15 * KIND, either express or implied.
17 ****************************************************************************/
20 #include <QtCore>
22 #include "bootloaderinstallbase.h"
23 #include "bootloaderinstallmi4.h"
24 #include "bootloaderinstallhex.h"
25 #include "bootloaderinstallipod.h"
26 #include "bootloaderinstallsansa.h"
27 #include "bootloaderinstallfile.h"
28 #include "bootloaderinstallchinachip.h"
29 #include "bootloaderinstallams.h"
30 #include "bootloaderinstalltcc.h"
31 #include "bootloaderinstallmpio.h"
32 #include "bootloaderinstallimx.h"
33 #include "utils.h"
35 #if defined(Q_OS_MACX)
36 #include <sys/param.h>
37 #include <sys/ucred.h>
38 #include <sys/mount.h>
39 #endif
42 BootloaderInstallBase* BootloaderInstallBase::createBootloaderInstaller(QObject* parent,QString type)
44 if(type == "mi4") {
45 return new BootloaderInstallMi4(parent);
47 else if(type == "hex") {
48 return new BootloaderInstallHex(parent);
50 else if(type == "sansa") {
51 return new BootloaderInstallSansa(parent);
53 else if(type == "ipod") {
54 return new BootloaderInstallIpod(parent);
56 else if(type == "file") {
57 return new BootloaderInstallFile(parent);
59 else if(type == "chinachip") {
60 return new BootloaderInstallChinaChip(parent);
62 else if(type == "ams") {
63 return new BootloaderInstallAms(parent);
65 else if(type == "tcc") {
66 return new BootloaderInstallTcc(parent);
68 else if(type == "mpio") {
69 return new BootloaderInstallMpio(parent);
71 else if(type == "imx") {
72 return new BootloaderInstallImx(parent);
74 else {
75 return NULL;
80 BootloaderInstallBase::BootloaderType BootloaderInstallBase::installed(void)
82 return BootloaderUnknown;
86 BootloaderInstallBase::Capabilities BootloaderInstallBase::capabilities(void)
88 return 0;
92 void BootloaderInstallBase::downloadBlStart(QUrl source)
94 m_http.setFile(&m_tempfile);
95 m_http.setCache(true);
96 connect(&m_http, SIGNAL(done(bool)), this, SLOT(downloadBlFinish(bool)));
97 // connect the http read signal to our logProgess *signal*
98 // to immediately emit it without any helper function.
99 connect(&m_http, SIGNAL(dataReadProgress(int, int)),
100 this, SIGNAL(logProgress(int, int)));
101 m_http.getFile(source);
105 void BootloaderInstallBase::downloadReqFinished(int id, bool error)
107 qDebug() << "[BootloaderInstallBase] Download Request" << id
108 << "finished, error:" << m_http.errorString();
110 downloadBlFinish(error);
114 void BootloaderInstallBase::downloadBlFinish(bool error)
116 qDebug() << "[BootloaderInstallBase] Downloading bootloader finished, error:"
117 << error;
119 // update progress bar
120 emit logProgress(100, 100);
122 if(m_http.httpResponse() != 200) {
123 emit logItem(tr("Download error: received HTTP error %1.")
124 .arg(m_http.errorString()), LOGERROR);
125 emit done(true);
126 return;
128 if(error) {
129 emit logItem(tr("Download error: %1")
130 .arg(m_http.error()), LOGERROR);
131 emit done(true);
132 return;
134 else if(m_http.isCached())
135 emit logItem(tr("Download finished (cache used)."), LOGOK);
136 else
137 emit logItem(tr("Download finished."), LOGOK);
139 QCoreApplication::processEvents();
140 m_blversion = m_http.timestamp();
141 emit downloadDone();
144 void BootloaderInstallBase::installBlfile(void)
146 qDebug() << "[BootloaderInstallBase] installBlFile(void)";
150 //! @brief backup OF file.
151 //! @param to folder to write backup file to. Folder will get created.
152 //! @return true on success, false on error.
154 bool BootloaderInstallBase::backup(QString to)
156 qDebug() << "[BootloaderInstallBase] Backing up bootloader file";
157 QDir targetDir(".");
158 emit logItem(tr("Creating backup of original firmware file."), LOGINFO);
159 if(!targetDir.mkpath(to)) {
160 emit logItem(tr("Creating backup folder failed"), LOGERROR);
161 return false;
163 QString tofile = to + "/" + QFileInfo(m_blfile).fileName();
164 qDebug() << "[BootloaderInstallBase] trying to backup" << m_blfile << "to" << tofile;
165 if(!QFile::copy(Utils::resolvePathCase(m_blfile), tofile)) {
166 emit logItem(tr("Creating backup copy failed."), LOGERROR);
167 return false;
169 emit logItem(tr("Backup created."), LOGOK);
170 return true;
174 //! @brief log installation to logfile.
175 //! @param mode action to perform. 0: add to log, 1: remove from log.
176 //! @return 0 on success
177 int BootloaderInstallBase::logInstall(LogMode mode)
179 int result = 0;
180 QString section = m_blurl.path().section('/', -1);
181 QSettings s(m_logfile, QSettings::IniFormat, this);
182 emit logItem(tr("Creating installation log"), LOGINFO);
184 if(mode == LogAdd) {
185 s.setValue("Bootloader/" + section, m_blversion.toString(Qt::ISODate));
186 qDebug() << "[BootloaderInstallBase] Writing log, version:"
187 << m_blversion.toString(Qt::ISODate);
189 else {
190 s.remove("Bootloader/" + section);
192 s.sync();
194 emit logItem(tr("Installation log created"), LOGOK);
196 return result;
200 //! @brief Return post install hints string.
201 //! @param model model string
202 //! @return hints.
203 QString BootloaderInstallBase::postinstallHints(QString model)
205 bool hint = false;
206 QString msg = tr("Bootloader installation is almost complete. "
207 "Installation <b>requires</b> you to perform the "
208 "following steps manually:");
210 msg += "<ol>";
211 msg += tr("<li>Safely remove your player.</li>");
212 if(model == "sansafuzeplus") {
213 msg += tr("<li>Remove any previously inserted microSD card</li>");
214 hint = true;
216 if(model == "h100" || model == "h120" || model == "h300" ||
217 model == "ondavx747") {
218 hint = true;
219 msg += tr("<li>Reboot your player into the original firmware.</li>"
220 "<li>Perform a firmware upgrade using the update functionality "
221 "of the original firmware. Please refer to your player's manual "
222 "on details.<br/><b>Important:</b> updating the firmware is a "
223 "critical process that must not be interrupted. <b>Make sure the "
224 "player is charged before starting the firmware update "
225 "process.</b></li>"
226 "<li>After the firmware has been updated reboot your player.</li>");
228 if(model == "sansafuzeplus") {
229 hint = true;
230 msg += tr("<li>Disconnect your player. The player will reboot and "
231 "perform an update of the original firmware. "
232 "Please refer to your players manual on details.<br/>"
233 "<b>Important:</b> updating the firmware is a "
234 "critical process that must not be interrupted. <b>Make sure the "
235 "player is charged before disconnecting the player.</b></li>"
236 "<li>After the firmware has been updated reboot your player.</li>");
238 if(model == "iaudiox5" || model == "iaudiom5"
239 || model == "iaudiox5v" || model == "iaudiom3" || model == "mpioh200") {
240 hint = true;
241 msg += tr("<li>Turn the player off</li>"
242 "<li>Insert the charger</li>");
244 if(model == "gigabeatf") {
245 hint = true;
246 msg += tr("<li>Unplug USB and power adaptors</li>"
247 "<li>Hold <i>Power</i> to turn the player off</li>"
248 "<li>Toggle the battery switch on the player</li>"
249 "<li>Hold <i>Power</i> to boot into Rockbox</li>");
251 msg += "</ol>";
252 msg += tr("<p><b>Note:</b> You can safely install other parts first, but "
253 "the above steps are <b>required</b> to finish the installation!</p>");
255 if(hint)
256 return msg;
257 else
258 return QString("");
262 #if defined(Q_OS_MACX)
263 void BootloaderInstallBase::waitRemount()
265 m_remountTries = 600;
266 emit logItem(tr("Waiting for system to remount player"), LOGINFO);
268 QTimer::singleShot(100, this, SLOT(checkRemount()));
270 #endif
273 void BootloaderInstallBase::checkRemount()
275 #if defined(Q_OS_MACX)
276 if(m_remountTries--) {
277 int status = 0;
278 // check if device has been remounted
279 QCoreApplication::processEvents();
280 int num;
281 struct statfs *mntinf;
283 num = getmntinfo(&mntinf, MNT_WAIT);
284 while(num--) {
285 if(QString(mntinf->f_mntfromname).startsWith(m_remountDevice)
286 && QString(mntinf->f_fstypename).contains("msdos", Qt::CaseInsensitive))
287 status = 1;
288 mntinf++;
290 if(!status) {
291 // still not remounted, restart timer.
292 QTimer::singleShot(500, this, SLOT(checkRemount()));
293 qDebug() << "[BootloaderInstallBase] Player not remounted yet" << m_remountDevice;
295 else {
296 emit logItem(tr("Player remounted"), LOGINFO);
297 emit remounted(true);
300 else {
301 emit logItem(tr("Timeout on remount"), LOGERROR);
302 emit remounted(false);
304 #endif
308 //! @brief set list of possible bootloader files and pick the existing one.
309 //! @param sl list of possible bootloader files.
310 void BootloaderInstallBase::setBlFile(QStringList sl)
312 // figue which of the possible bootloader filenames is correct.
313 for(int a = 0; a < sl.size(); a++) {
314 if(!Utils::resolvePathCase(sl.at(a)).isEmpty()) {
315 m_blfile = sl.at(a);
318 if(m_blfile.isEmpty()) {
319 m_blfile = sl.at(0);