Use a nice apostroph
[kugel-rb.git] / rbutil / rbutilqt / base / bootloaderinstallsansa.cpp
blob0dc94c553c353cf3ee9abc6744063fccd341c82a
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
9 * Copyright (C) 2008 by Dominik Riebeling
10 * $Id$
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 ****************************************************************************/
20 #include <QtCore>
21 #include "bootloaderinstallbase.h"
22 #include "bootloaderinstallsansa.h"
24 #include "../sansapatcher/sansapatcher.h"
25 #include "autodetection.h"
27 BootloaderInstallSansa::BootloaderInstallSansa(QObject *parent)
28 : BootloaderInstallBase(parent)
30 (void)parent;
31 // initialize sector buffer. sansa_sectorbuf is instantiated by
32 // sansapatcher.
33 // The buffer itself is only present once, so make sure to not allocate
34 // it if it was already allocated. The application needs to take care
35 // no concurrent (i.e. multiple objects of this class running) requests
36 // are done.
37 if(sansa_sectorbuf == NULL)
38 sansa_alloc_buffer(&sansa_sectorbuf, BUFFER_SIZE);
42 BootloaderInstallSansa::~BootloaderInstallSansa()
44 if(sansa_sectorbuf) {
45 free(sansa_sectorbuf);
46 sansa_sectorbuf = NULL;
51 /** Start bootloader installation.
53 bool BootloaderInstallSansa::install(void)
55 if(sansa_sectorbuf == NULL) {
56 emit logItem(tr("Error: can't allocate buffer memory!"), LOGERROR);
57 return false;
58 emit done(true);
61 emit logItem(tr("Searching for Sansa"), LOGINFO);
63 struct sansa_t sansa;
65 int n = sansa_scan(&sansa);
66 if(n == -1) {
67 emit logItem(tr("Permission for disc access denied!\n"
68 "This is required to install the bootloader"),
69 LOGERROR);
70 emit done(true);
71 return false;
73 if(n == 0) {
74 emit logItem(tr("No Sansa detected!"), LOGERROR);
75 emit done(true);
76 return false;
78 if(sansa.hasoldbootloader) {
79 emit logItem(tr("OLD ROCKBOX INSTALLATION DETECTED, ABORTING.\n"
80 "You must reinstall the original Sansa firmware before running\n"
81 "sansapatcher for the first time.\n"
82 "See http://www.rockbox.org/wiki/SansaE200Install\n"),
83 LOGERROR);
84 emit done(true);
85 return false;
87 emit logItem(tr("Downloading bootloader file"), LOGINFO);
89 downloadBlStart(m_blurl);
90 connect(this, SIGNAL(downloadDone()), this, SLOT(installStage2()));
91 return true;
95 /** Finish bootloader installation.
97 void BootloaderInstallSansa::installStage2(void)
99 struct sansa_t sansa;
101 emit logItem(tr("Installing Rockbox bootloader"), LOGINFO);
102 QCoreApplication::processEvents();
103 if(!sansaInitialize(&sansa)) {
104 emit done(true);
105 return;
108 if(sansa_reopen_rw(&sansa) < 0) {
109 emit logItem(tr("Could not open Sansa in R/W mode"), LOGERROR);
110 emit done(true);
111 return;
114 // check model -- if sansapatcher reports a c200 don't install an e200
115 // bootloader and vice versa.
116 // The model is available in the mi4 file at offset 0x1fc and matches
117 // the targetname set by sansapatcher.
118 emit logItem(tr("Checking downloaded bootloader"), LOGINFO);
119 m_tempfile.open();
120 QString blfile = m_tempfile.fileName();
121 char magic[4];
122 m_tempfile.seek(0x1fc);
123 m_tempfile.read(magic, 4);
124 m_tempfile.close();
125 if(memcmp(sansa.targetname, magic, 4) != 0) {
126 emit logItem(tr("Bootloader mismatch! Aborting."), LOGERROR);
127 qDebug("[BootloaderInstallSansa] Targetname: %s, mi4 magic: %c%c%c%c",
128 sansa.targetname, magic[0], magic[1], magic[2], magic[3]);
129 emit done(true);
130 sansa_close(&sansa);
131 return;
134 if(sansa_add_bootloader(&sansa, blfile.toLatin1().data(),
135 FILETYPE_MI4) == 0) {
136 emit logItem(tr("Successfully installed bootloader"), LOGOK);
137 sansa_close(&sansa);
138 #if defined(Q_OS_MACX)
139 m_remountDevice = sansa.diskname;
140 connect(this, SIGNAL(remounted(bool)), this, SLOT(installStage3(bool)));
141 waitRemount();
142 #else
143 installStage3(true);
144 #endif
146 else {
147 emit logItem(tr("Failed to install bootloader"), LOGERROR);
148 sansa_close(&sansa);
149 emit done(true);
150 return;
156 void BootloaderInstallSansa::installStage3(bool mounted)
158 if(mounted) {
159 logInstall(LogAdd);
160 emit logItem(tr("Bootloader Installation complete."), LOGINFO);
161 emit done(false);
162 return;
164 else {
165 emit logItem(tr("Writing log aborted"), LOGERROR);
166 emit done(true);
168 qDebug() << "version installed:" << m_blversion.toString(Qt::ISODate);
172 /** Uninstall the bootloader.
174 bool BootloaderInstallSansa::uninstall(void)
176 struct sansa_t sansa;
178 emit logItem(tr("Uninstalling bootloader"), LOGINFO);
179 QCoreApplication::processEvents();
181 if(!sansaInitialize(&sansa)) {
182 emit done(true);
183 return false;
186 if (sansa.hasoldbootloader) {
187 emit logItem(tr("OLD ROCKBOX INSTALLATION DETECTED, ABORTING.\n"
188 "You must reinstall the original Sansa firmware before running\n"
189 "sansapatcher for the first time.\n"
190 "See http://www.rockbox.org/wiki/SansaE200Install\n"),
191 LOGERROR);
192 emit done(true);
193 return false;
196 if (sansa_reopen_rw(&sansa) < 0) {
197 emit logItem(tr("Could not open Sansa in R/W mode"), LOGERROR);
198 emit done(true);
199 return false;
202 if (sansa_delete_bootloader(&sansa)==0) {
203 emit logItem(tr("Successfully removed bootloader"), LOGOK);
204 logInstall(LogRemove);
205 emit done(false);
206 sansa_close(&sansa);
207 return true;
209 else {
210 emit logItem(tr("Removing bootloader failed."),LOGERROR);
211 emit done(true);
212 sansa_close(&sansa);
213 return false;
216 return false;
220 /** Check if bootloader is already installed
222 BootloaderInstallBase::BootloaderType BootloaderInstallSansa::installed(void)
224 struct sansa_t sansa;
225 int num;
227 if(!sansaInitialize(&sansa)) {
228 return BootloaderUnknown;
230 if((num = sansa_list_images(&sansa)) == 2) {
231 sansa_close(&sansa);
232 return BootloaderRockbox;
234 else if(num == 1) {
235 sansa_close(&sansa);
236 return BootloaderOther;
238 return BootloaderUnknown;
242 bool BootloaderInstallSansa::sansaInitialize(struct sansa_t *sansa)
244 if(!m_blfile.isEmpty()) {
245 QString devicename = Autodetection::resolveDevicename(m_blfile);
246 if(devicename.isEmpty()) {
247 emit logItem(tr("Error: could not retrieve device name"), LOGERROR);
248 return false;
250 #if defined(Q_OS_WIN32)
251 sprintf(sansa->diskname, "\\\\.\\PhysicalDrive%i", devicename.toInt());
252 #elif defined(Q_OS_MACX)
253 sprintf(sansa->diskname,
254 qPrintable(devicename.remove(QRegExp("s[0-9]+$"))));
255 #else
256 sprintf(sansa->diskname,
257 qPrintable(devicename.remove(QRegExp("[0-9]+$"))));
258 #endif
259 qDebug() << "[BootloaderInstallSansa] sansapatcher: overriding scan, using"
260 << sansa->diskname;
262 else if(sansa_scan(sansa) != 1) {
263 emit logItem(tr("Can't find Sansa"), LOGERROR);
264 return false;
267 if (sansa_open(sansa, 0) < 0) {
268 emit logItem(tr("Could not open Sansa"), LOGERROR);
269 return false;
272 if (sansa_read_partinfo(sansa,0) < 0) {
273 emit logItem(tr("Could not read partition table"), LOGERROR);
274 sansa_close(sansa);
275 return false;
278 int i = is_sansa(sansa);
279 if(i < 0) {
280 emit logItem(tr("Disk is not a Sansa (Error %1), aborting.").arg(i), LOGERROR);
281 sansa_close(sansa);
282 return false;
284 return true;
288 /** Get capabilities of subclass installer.
290 BootloaderInstallBase::Capabilities BootloaderInstallSansa::capabilities(void)
292 return (Install | Uninstall | IsRaw | CanCheckInstalled);