Handle language change events in widgets.
[maemo-rb.git] / rbutil / rbutilqt / base / bootloaderinstallsansa.cpp
blobb05839e2973d8c4cd9b5aedfbe2ccc7be867faa2
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 ****************************************************************************/
19 #include <QtCore>
20 #include "bootloaderinstallbase.h"
21 #include "bootloaderinstallsansa.h"
23 #include "../sansapatcher/sansapatcher.h"
24 #include "utils.h"
26 BootloaderInstallSansa::BootloaderInstallSansa(QObject *parent)
27 : BootloaderInstallBase(parent)
29 (void)parent;
30 // initialize sector buffer. sansa_sectorbuf is instantiated by
31 // sansapatcher.
32 // The buffer itself is only present once, so make sure to not allocate
33 // it if it was already allocated. The application needs to take care
34 // no concurrent (i.e. multiple objects of this class running) requests
35 // are done.
36 if(sansa_sectorbuf == NULL)
37 sansa_alloc_buffer(&sansa_sectorbuf, BUFFER_SIZE);
41 BootloaderInstallSansa::~BootloaderInstallSansa()
43 if(sansa_sectorbuf) {
44 free(sansa_sectorbuf);
45 sansa_sectorbuf = NULL;
50 /** Start bootloader installation.
52 bool BootloaderInstallSansa::install(void)
54 if(sansa_sectorbuf == NULL) {
55 emit logItem(tr("Error: can't allocate buffer memory!"), LOGERROR);
56 return false;
57 emit done(true);
60 emit logItem(tr("Searching for Sansa"), LOGINFO);
62 struct sansa_t sansa;
64 int n = sansa_scan(&sansa);
65 if(n == -1) {
66 emit logItem(tr("Permission for disc access denied!\n"
67 "This is required to install the bootloader"),
68 LOGERROR);
69 emit done(true);
70 return false;
72 if(n == 0) {
73 emit logItem(tr("No Sansa detected!"), LOGERROR);
74 emit done(true);
75 return false;
77 if(sansa.hasoldbootloader) {
78 emit logItem(tr("OLD ROCKBOX INSTALLATION DETECTED, ABORTING.\n"
79 "You must reinstall the original Sansa firmware before running\n"
80 "sansapatcher for the first time.\n"
81 "See http://www.rockbox.org/wiki/SansaE200Install\n"),
82 LOGERROR);
83 emit done(true);
84 return false;
86 emit logItem(tr("Downloading bootloader file"), LOGINFO);
88 downloadBlStart(m_blurl);
89 connect(this, SIGNAL(downloadDone()), this, SLOT(installStage2()));
90 return true;
94 /** Finish bootloader installation.
96 void BootloaderInstallSansa::installStage2(void)
98 struct sansa_t sansa;
99 unsigned char* buf = NULL;
100 unsigned int len;
102 emit logItem(tr("Installing Rockbox bootloader"), LOGINFO);
103 QCoreApplication::processEvents();
104 if(!sansaInitialize(&sansa)) {
105 emit done(true);
106 return;
109 if(sansa_reopen_rw(&sansa) < 0) {
110 emit logItem(tr("Could not open Sansa in R/W mode"), LOGERROR);
111 emit done(true);
112 return;
115 // check model -- if sansapatcher reports a c200 don't install an e200
116 // bootloader and vice versa.
117 // The model is available in the mi4 file at offset 0x1fc and matches
118 // the targetname set by sansapatcher.
119 emit logItem(tr("Checking downloaded bootloader"), LOGINFO);
120 m_tempfile.open();
121 QString blfile = m_tempfile.fileName();
122 char magic[4];
123 m_tempfile.seek(0x1fc);
124 m_tempfile.read(magic, 4);
125 m_tempfile.close();
126 if(memcmp(sansa.targetname, magic, 4) != 0) {
127 emit logItem(tr("Bootloader mismatch! Aborting."), LOGERROR);
128 qDebug("[BootloaderInstallSansa] Targetname: %s, mi4 magic: %c%c%c%c",
129 sansa.targetname, magic[0], magic[1], magic[2], magic[3]);
130 emit done(true);
131 sansa_close(&sansa);
132 return;
135 len = sansa_read_bootloader(&sansa, blfile.toLatin1().data(), &buf);
136 if(sansa_add_bootloader(&sansa, buf, len) == 0) {
137 emit logItem(tr("Successfully installed bootloader"), LOGOK);
138 sansa_close(&sansa);
139 #if defined(Q_OS_MACX)
140 m_remountDevice = sansa.diskname;
141 connect(this, SIGNAL(remounted(bool)), this, SLOT(installStage3(bool)));
142 waitRemount();
143 #else
144 installStage3(true);
145 #endif
147 else {
148 emit logItem(tr("Failed to install bootloader"), LOGERROR);
149 sansa_close(&sansa);
150 emit done(true);
151 return;
157 void BootloaderInstallSansa::installStage3(bool mounted)
159 if(mounted) {
160 logInstall(LogAdd);
161 emit logItem(tr("Bootloader Installation complete."), LOGINFO);
162 emit done(false);
163 return;
165 else {
166 emit logItem(tr("Writing log aborted"), LOGERROR);
167 emit done(true);
169 qDebug() << "[BootloaderInstallSansa] version installed:" << m_blversion.toString(Qt::ISODate);
173 /** Uninstall the bootloader.
175 bool BootloaderInstallSansa::uninstall(void)
177 struct sansa_t sansa;
179 emit logItem(tr("Uninstalling bootloader"), LOGINFO);
180 QCoreApplication::processEvents();
182 if(!sansaInitialize(&sansa)) {
183 emit done(true);
184 return false;
187 if (sansa.hasoldbootloader) {
188 emit logItem(tr("OLD ROCKBOX INSTALLATION DETECTED, ABORTING.\n"
189 "You must reinstall the original Sansa firmware before running\n"
190 "sansapatcher for the first time.\n"
191 "See http://www.rockbox.org/wiki/SansaE200Install\n"),
192 LOGERROR);
193 emit done(true);
194 return false;
197 if (sansa_reopen_rw(&sansa) < 0) {
198 emit logItem(tr("Could not open Sansa in R/W mode"), LOGERROR);
199 emit done(true);
200 return false;
203 if (sansa_delete_bootloader(&sansa)==0) {
204 emit logItem(tr("Successfully removed bootloader"), LOGOK);
205 logInstall(LogRemove);
206 emit done(false);
207 sansa_close(&sansa);
208 return true;
210 else {
211 emit logItem(tr("Removing bootloader failed."),LOGERROR);
212 emit done(true);
213 sansa_close(&sansa);
214 return false;
217 return false;
221 /** Check if bootloader is already installed
223 BootloaderInstallBase::BootloaderType BootloaderInstallSansa::installed(void)
225 struct sansa_t sansa;
226 int num;
228 if(!sansaInitialize(&sansa)) {
229 return BootloaderUnknown;
231 if((num = sansa_list_images(&sansa)) == 2) {
232 sansa_close(&sansa);
233 return BootloaderRockbox;
235 else if(num == 1) {
236 sansa_close(&sansa);
237 return BootloaderOther;
239 return BootloaderUnknown;
243 bool BootloaderInstallSansa::sansaInitialize(struct sansa_t *sansa)
245 if(!m_blfile.isEmpty()) {
246 QString devicename = Utils::resolveDevicename(m_blfile);
247 if(devicename.isEmpty()) {
248 emit logItem(tr("Error: could not retrieve device name"), LOGERROR);
249 return false;
251 #if defined(Q_OS_WIN32)
252 sprintf(sansa->diskname, "\\\\.\\PhysicalDrive%i", devicename.toInt());
253 #elif defined(Q_OS_MACX)
254 sprintf(sansa->diskname,
255 qPrintable(devicename.remove(QRegExp("s[0-9]+$"))));
256 #else
257 sprintf(sansa->diskname,
258 qPrintable(devicename.remove(QRegExp("[0-9]+$"))));
259 #endif
260 qDebug() << "[BootloaderInstallSansa] sansapatcher: overriding scan, using"
261 << sansa->diskname;
263 else if(sansa_scan(sansa) != 1) {
264 emit logItem(tr("Can't find Sansa"), LOGERROR);
265 return false;
268 if (sansa_open(sansa, 0) < 0) {
269 emit logItem(tr("Could not open Sansa"), LOGERROR);
270 return false;
273 if (sansa_read_partinfo(sansa,0) < 0) {
274 emit logItem(tr("Could not read partition table"), LOGERROR);
275 sansa_close(sansa);
276 return false;
279 int i = is_sansa(sansa);
280 if(i < 0) {
281 emit logItem(tr("Disk is not a Sansa (Error %1), aborting.").arg(i), LOGERROR);
282 sansa_close(sansa);
283 return false;
285 return true;
289 /** Get capabilities of subclass installer.
291 BootloaderInstallBase::Capabilities BootloaderInstallSansa::capabilities(void)
293 return (Install | Uninstall | IsRaw | CanCheckInstalled);