Bump version numbers for 3.13
[maemo-rb.git] / rbutil / rbutilqt / base / bootloaderinstallsansa.cpp
blob49099ebaf80e5a9c1b2bb7c3a861a9119ea161b8
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. The sector buffer is part of the sansa_t
31 // structure, so a second instance of this class will have its own buffer.
32 sansa_alloc_buffer(&sansa, BUFFER_SIZE);
36 BootloaderInstallSansa::~BootloaderInstallSansa()
38 if(sansa.sectorbuf) {
39 sansa_dealloc_buffer(&sansa);
44 /** Start bootloader installation.
46 bool BootloaderInstallSansa::install(void)
48 if(sansa.sectorbuf == NULL) {
49 emit logItem(tr("Error: can't allocate buffer memory!"), LOGERROR);
50 return false;
51 emit done(true);
54 emit logItem(tr("Searching for Sansa"), LOGINFO);
56 int n = sansa_scan(&sansa);
57 if(n == -1) {
58 emit logItem(tr("Permission for disc access denied!\n"
59 "This is required to install the bootloader"),
60 LOGERROR);
61 emit done(true);
62 return false;
64 if(n == 0) {
65 emit logItem(tr("No Sansa detected!"), LOGERROR);
66 emit done(true);
67 return false;
69 if(sansa.hasoldbootloader) {
70 emit logItem(tr("OLD ROCKBOX INSTALLATION DETECTED, ABORTING.\n"
71 "You must reinstall the original Sansa firmware before running\n"
72 "sansapatcher for the first time.\n"
73 "See http://www.rockbox.org/wiki/SansaE200Install\n"),
74 LOGERROR);
75 emit done(true);
76 return false;
78 emit logItem(tr("Downloading bootloader file"), LOGINFO);
80 downloadBlStart(m_blurl);
81 connect(this, SIGNAL(downloadDone()), this, SLOT(installStage2()));
82 return true;
86 /** Finish bootloader installation.
88 void BootloaderInstallSansa::installStage2(void)
90 unsigned char* buf = NULL;
91 unsigned int len;
93 emit logItem(tr("Installing Rockbox bootloader"), LOGINFO);
94 QCoreApplication::processEvents();
95 if(!sansaInitialize(&sansa)) {
96 emit done(true);
97 return;
100 if(sansa_reopen_rw(&sansa) < 0) {
101 emit logItem(tr("Could not open Sansa in R/W mode"), LOGERROR);
102 emit done(true);
103 return;
106 // check model -- if sansapatcher reports a c200 don't install an e200
107 // bootloader and vice versa.
108 // The model is available in the mi4 file at offset 0x1fc and matches
109 // the targetname set by sansapatcher.
110 emit logItem(tr("Checking downloaded bootloader"), LOGINFO);
111 m_tempfile.open();
112 QString blfile = m_tempfile.fileName();
113 char magic[4];
114 m_tempfile.seek(0x1fc);
115 m_tempfile.read(magic, 4);
116 m_tempfile.close();
117 if(memcmp(sansa.targetname, magic, 4) != 0) {
118 emit logItem(tr("Bootloader mismatch! Aborting."), LOGERROR);
119 qDebug("[BootloaderInstallSansa] Targetname: %s, mi4 magic: %c%c%c%c",
120 sansa.targetname, magic[0], magic[1], magic[2], magic[3]);
121 emit done(true);
122 sansa_close(&sansa);
123 return;
126 len = sansa_read_bootloader(&sansa, blfile.toLatin1().data(), &buf);
127 if(sansa_add_bootloader(&sansa, buf, len) == 0) {
128 emit logItem(tr("Successfully installed bootloader"), LOGOK);
129 sansa_close(&sansa);
130 #if defined(Q_OS_MACX)
131 m_remountDevice = sansa.diskname;
132 connect(this, SIGNAL(remounted(bool)), this, SLOT(installStage3(bool)));
133 waitRemount();
134 #else
135 installStage3(true);
136 #endif
138 else {
139 emit logItem(tr("Failed to install bootloader"), LOGERROR);
140 sansa_close(&sansa);
141 emit done(true);
142 return;
148 void BootloaderInstallSansa::installStage3(bool mounted)
150 if(mounted) {
151 logInstall(LogAdd);
152 emit logItem(tr("Bootloader Installation complete."), LOGINFO);
153 emit done(false);
154 return;
156 else {
157 emit logItem(tr("Writing log aborted"), LOGERROR);
158 emit done(true);
160 qDebug() << "[BootloaderInstallSansa] version installed:" << m_blversion.toString(Qt::ISODate);
164 /** Uninstall the bootloader.
166 bool BootloaderInstallSansa::uninstall(void)
168 emit logItem(tr("Uninstalling bootloader"), LOGINFO);
169 QCoreApplication::processEvents();
171 if(!sansaInitialize(&sansa)) {
172 emit done(true);
173 return false;
176 if (sansa.hasoldbootloader) {
177 emit logItem(tr("OLD ROCKBOX INSTALLATION DETECTED, ABORTING.\n"
178 "You must reinstall the original Sansa firmware before running\n"
179 "sansapatcher for the first time.\n"
180 "See http://www.rockbox.org/wiki/SansaE200Install\n"),
181 LOGERROR);
182 emit done(true);
183 return false;
186 if (sansa_reopen_rw(&sansa) < 0) {
187 emit logItem(tr("Could not open Sansa in R/W mode"), LOGERROR);
188 emit done(true);
189 return false;
192 if (sansa_delete_bootloader(&sansa)==0) {
193 emit logItem(tr("Successfully removed bootloader"), LOGOK);
194 logInstall(LogRemove);
195 emit done(false);
196 sansa_close(&sansa);
197 return true;
199 else {
200 emit logItem(tr("Removing bootloader failed."),LOGERROR);
201 emit done(true);
202 sansa_close(&sansa);
203 return false;
206 return false;
210 /** Check if bootloader is already installed
212 BootloaderInstallBase::BootloaderType BootloaderInstallSansa::installed(void)
214 int num;
216 if(!sansaInitialize(&sansa)) {
217 return BootloaderUnknown;
219 if((num = sansa_list_images(&sansa)) == 2) {
220 sansa_close(&sansa);
221 return BootloaderRockbox;
223 else if(num == 1) {
224 sansa_close(&sansa);
225 return BootloaderOther;
227 return BootloaderUnknown;
231 bool BootloaderInstallSansa::sansaInitialize(struct sansa_t *sansa)
233 if(!m_blfile.isEmpty()) {
234 QString devicename = Utils::resolveDevicename(m_blfile);
235 if(devicename.isEmpty()) {
236 emit logItem(tr("Error: could not retrieve device name"), LOGERROR);
237 return false;
239 #if defined(Q_OS_WIN32)
240 sprintf(sansa->diskname, "\\\\.\\PhysicalDrive%i", devicename.toInt());
241 #elif defined(Q_OS_MACX)
242 sprintf(sansa->diskname,
243 qPrintable(devicename.remove(QRegExp("s[0-9]+$"))));
244 #else
245 sprintf(sansa->diskname,
246 qPrintable(devicename.remove(QRegExp("[0-9]+$"))));
247 #endif
248 qDebug() << "[BootloaderInstallSansa] sansapatcher: overriding scan, using"
249 << sansa->diskname;
251 else if(sansa_scan(sansa) != 1) {
252 emit logItem(tr("Can't find Sansa"), LOGERROR);
253 return false;
256 if (sansa_open(sansa, 0) < 0) {
257 emit logItem(tr("Could not open Sansa"), LOGERROR);
258 return false;
261 if (sansa_read_partinfo(sansa,0) < 0) {
262 emit logItem(tr("Could not read partition table"), LOGERROR);
263 sansa_close(sansa);
264 return false;
267 int i = is_sansa(sansa);
268 if(i < 0) {
269 emit logItem(tr("Disk is not a Sansa (Error %1), aborting.").arg(i), LOGERROR);
270 sansa_close(sansa);
271 return false;
273 return true;
277 /** Get capabilities of subclass installer.
279 BootloaderInstallBase::Capabilities BootloaderInstallSansa::capabilities(void)
281 return (Install | Uninstall | IsRaw | CanCheckInstalled);