1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
9 * Copyright (C) 2008 by Dominik Riebeling
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 ****************************************************************************/
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
)
31 // initialize sector buffer. sansa_sectorbuf is instantiated by
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
37 if(sansa_sectorbuf
== NULL
)
38 sansa_alloc_buffer(&sansa_sectorbuf
, BUFFER_SIZE
);
42 BootloaderInstallSansa::~BootloaderInstallSansa()
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
);
61 emit
logItem(tr("Searching for Sansa"), LOGINFO
);
65 int n
= sansa_scan(&sansa
);
67 emit
logItem(tr("Permission for disc access denied!\n"
68 "This is required to install the bootloader"),
74 emit
logItem(tr("No Sansa detected!"), LOGERROR
);
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"),
87 emit
logItem(tr("Downloading bootloader file"), LOGINFO
);
89 downloadBlStart(m_blurl
);
90 connect(this, SIGNAL(downloadDone()), this, SLOT(installStage2()));
95 /** Finish bootloader installation.
97 void BootloaderInstallSansa::installStage2(void)
101 emit
logItem(tr("Installing Rockbox bootloader"), LOGINFO
);
102 QCoreApplication::processEvents();
103 if(!sansaInitialize(&sansa
)) {
108 if(sansa_reopen_rw(&sansa
) < 0) {
109 emit
logItem(tr("Could not open Sansa in R/W mode"), LOGERROR
);
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
);
120 QString blfile
= m_tempfile
.fileName();
122 m_tempfile
.seek(0x1fc);
123 m_tempfile
.read(magic
, 4);
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]);
134 if(sansa_add_bootloader(&sansa
, blfile
.toLatin1().data(),
135 FILETYPE_MI4
) == 0) {
136 emit
logItem(tr("Successfully installed bootloader"), LOGOK
);
143 emit
logItem(tr("Failed to install bootloader"), LOGERROR
);
152 /** Uninstall the bootloader.
154 bool BootloaderInstallSansa::uninstall(void)
156 struct sansa_t sansa
;
158 emit
logItem(tr("Uninstalling bootloader"), LOGINFO
);
159 QCoreApplication::processEvents();
161 if(!sansaInitialize(&sansa
)) {
166 if (sansa
.hasoldbootloader
) {
167 emit
logItem(tr("OLD ROCKBOX INSTALLATION DETECTED, ABORTING.\n"
168 "You must reinstall the original Sansa firmware before running\n"
169 "sansapatcher for the first time.\n"
170 "See http://www.rockbox.org/wiki/SansaE200Install\n"),
176 if (sansa_reopen_rw(&sansa
) < 0) {
177 emit
logItem(tr("Could not open Sansa in R/W mode"), LOGERROR
);
182 if (sansa_delete_bootloader(&sansa
)==0) {
183 emit
logItem(tr("Successfully removed bootloader"), LOGOK
);
184 logInstall(LogRemove
);
190 emit
logItem(tr("Removing bootloader failed."),LOGERROR
);
200 /** Check if bootloader is already installed
202 BootloaderInstallBase::BootloaderType
BootloaderInstallSansa::installed(void)
204 struct sansa_t sansa
;
207 if(!sansaInitialize(&sansa
)) {
208 return BootloaderUnknown
;
210 if((num
= sansa_list_images(&sansa
)) == 2) {
212 return BootloaderRockbox
;
216 return BootloaderOther
;
218 return BootloaderUnknown
;
222 bool BootloaderInstallSansa::sansaInitialize(struct sansa_t
*sansa
)
224 if(!m_blfile
.isEmpty()) {
225 #if defined(Q_OS_WIN32)
226 sprintf(sansa
->diskname
, "\\\\.\\PhysicalDrive%i",
227 Autodetection::resolveDevicename(m_blfile
).toInt());
228 #elif defined(Q_OS_MACX)
229 sprintf(sansa
->diskname
,
230 qPrintable(Autodetection::resolveDevicename(m_blfile
).remove(QRegExp("s[0-9]+$"))));
232 sprintf(sansa
->diskname
,
233 qPrintable(Autodetection::resolveDevicename(m_blfile
).remove(QRegExp("[0-9]+$"))));
235 qDebug() << "[BootloaderInstallSansa] sansapatcher: overriding scan, using"
238 else if(sansa_scan(sansa
) != 1) {
239 emit
logItem(tr("Can't find Sansa"), LOGERROR
);
243 if (sansa_open(sansa
, 0) < 0) {
244 emit
logItem(tr("Could not open Sansa"), LOGERROR
);
248 if (sansa_read_partinfo(sansa
,0) < 0) {
249 emit
logItem(tr("Could not read partition table"), LOGERROR
);
254 int i
= is_sansa(sansa
);
256 emit
logItem(tr("Disk is not a Sansa (Error %1), aborting.").arg(i
), LOGERROR
);
264 /** Get capabilities of subclass installer.
266 BootloaderInstallBase::Capabilities
BootloaderInstallSansa::capabilities(void)
268 return (Install
| Uninstall
| IsRaw
| CanCheckInstalled
);