Rearange menu of mpegplayer. Add new menu with "settings" and "quit", and remove...
[kugel-rb.git] / rbutil / rbutilqt / base / bootloaderinstallsansa.cpp
blob43404de4bbe881159df462423417f4fa90db41d4
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 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 struct sansa_t sansa;
92 emit logItem(tr("Installing Rockbox bootloader"), LOGINFO);
93 QCoreApplication::processEvents();
94 if(!sansaInitialize(&sansa)) {
95 emit done(true);
96 return;
99 if(sansa.hasoldbootloader) {
100 emit logItem(tr("OLD ROCKBOX INSTALLATION DETECTED, ABORTING.\n"
101 "You must reinstall the original Sansa firmware before running\n"
102 "sansapatcher for the first time.\n"
103 "See http://www.rockbox.org/wiki/SansaE200Install\n"),
104 LOGERROR);
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 if(sansa_add_bootloader(&sansa, blfile.toLatin1().data(),
136 FILETYPE_MI4) == 0) {
137 emit logItem(tr("Successfully installed bootloader"), LOGOK);
138 logInstall(LogAdd);
139 emit done(false);
140 sansa_close(&sansa);
141 return;
143 else {
144 emit logItem(tr("Failed to install bootloader"), LOGERROR);
145 sansa_close(&sansa);
146 emit done(true);
147 return;
153 /** Uninstall the bootloader.
155 bool BootloaderInstallSansa::uninstall(void)
157 struct sansa_t sansa;
159 emit logItem(tr("Uninstalling bootloader"), LOGINFO);
160 QCoreApplication::processEvents();
162 if(!sansaInitialize(&sansa)) {
163 emit done(true);
164 return false;
167 if (sansa.hasoldbootloader) {
168 emit logItem(tr("OLD ROCKBOX INSTALLATION DETECTED, ABORTING.\n"
169 "You must reinstall the original Sansa firmware before running\n"
170 "sansapatcher for the first time.\n"
171 "See http://www.rockbox.org/wiki/SansaE200Install\n"),
172 LOGERROR);
173 emit done(true);
174 return false;
177 if (sansa_reopen_rw(&sansa) < 0) {
178 emit logItem(tr("Could not open Sansa in R/W mode"), LOGERROR);
179 emit done(true);
180 return false;
183 if (sansa_delete_bootloader(&sansa)==0) {
184 emit logItem(tr("Successfully removed bootloader"), LOGOK);
185 logInstall(LogRemove);
186 emit done(false);
187 sansa_close(&sansa);
188 return true;
190 else {
191 emit logItem(tr("Removing bootloader failed."),LOGERROR);
192 emit done(true);
193 sansa_close(&sansa);
194 return false;
197 return false;
201 /** Check if bootloader is already installed
203 BootloaderInstallBase::BootloaderType BootloaderInstallSansa::installed(void)
205 struct sansa_t sansa;
206 int num;
208 if(!sansaInitialize(&sansa)) {
209 return BootloaderUnknown;
211 if((num = sansa_list_images(&sansa)) == 2) {
212 sansa_close(&sansa);
213 return BootloaderRockbox;
215 else if(num == 1) {
216 sansa_close(&sansa);
217 return BootloaderOther;
219 return BootloaderUnknown;
223 bool BootloaderInstallSansa::sansaInitialize(struct sansa_t *sansa)
225 if(!m_blfile.isEmpty()) {
226 #if defined(Q_OS_WIN32)
227 sprintf(sansa->diskname, "\\\\.\\PhysicalDrive%i",
228 Autodetection::resolveDevicename(m_blfile).toInt());
229 #else
230 sprintf(sansa->diskname,
231 qPrintable(Autodetection::resolveDevicename(m_blfile).remove(QRegExp("[0-9]+$"))));
232 #endif
233 qDebug() << "[BootloaderInstallSansa] sansapatcher: overriding scan, using"
234 << sansa->diskname;
236 else if(sansa_scan(sansa) != 1) {
237 emit logItem(tr("Can't find Sansa"), LOGERROR);
238 return false;
241 if (sansa_open(sansa, 0) < 0) {
242 emit logItem(tr("Could not open Sansa"), LOGERROR);
243 return false;
246 if (sansa_read_partinfo(sansa,0) < 0) {
247 emit logItem(tr("Could not read partition table"), LOGERROR);
248 sansa_close(sansa);
249 return false;
252 int i = is_sansa(sansa);
253 if(i < 0) {
254 emit logItem(tr("Disk is not a Sansa (Error %1), aborting.").arg(i), LOGERROR);
255 sansa_close(sansa);
256 return false;
258 return true;
262 /** Get capabilities of subclass installer.
264 BootloaderInstallBase::Capabilities BootloaderInstallSansa::capabilities(void)
266 return (Install | Uninstall | IsRaw | CanCheckInstalled);