From c876d3bbefe0dc00c27ca0c12d29da5874946962 Mon Sep 17 00:00:00 2001 From: Dominik Riebeling Date: Wed, 15 Dec 2021 21:04:28 +0100 Subject: rbutil: Merge rbutil with utils folder. rbutil uses several components from the utils folder, and can be considered part of utils too. Having it in a separate folder is an arbitrary split that doesn't help anymore these days, so merge them. This also allows other utils to easily use libtools.make without the need to navigate to a different folder. Change-Id: I3fc2f4de19e3e776553efb5dea5f779dfec0dc21 --- utils/rbutilqt/base/bootloaderinstallsansa.cpp | 286 +++++++++++++++++++++++++ 1 file changed, 286 insertions(+) create mode 100644 utils/rbutilqt/base/bootloaderinstallsansa.cpp (limited to 'utils/rbutilqt/base/bootloaderinstallsansa.cpp') diff --git a/utils/rbutilqt/base/bootloaderinstallsansa.cpp b/utils/rbutilqt/base/bootloaderinstallsansa.cpp new file mode 100644 index 0000000000..b1f0167e42 --- /dev/null +++ b/utils/rbutilqt/base/bootloaderinstallsansa.cpp @@ -0,0 +1,286 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2008 by Dominik Riebeling + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include +#include "bootloaderinstallbase.h" +#include "bootloaderinstallsansa.h" +#include "Logger.h" + +#include "../sansapatcher/sansapatcher.h" +#include "utils.h" + +BootloaderInstallSansa::BootloaderInstallSansa(QObject *parent) + : BootloaderInstallBase(parent) +{ + (void)parent; + // initialize sector buffer. The sector buffer is part of the sansa_t + // structure, so a second instance of this class will have its own buffer. + sansa_alloc_buffer(&sansa, BUFFER_SIZE); +} + + +BootloaderInstallSansa::~BootloaderInstallSansa() +{ + if(sansa.sectorbuf) { + sansa_dealloc_buffer(&sansa); + } +} + + +/** Start bootloader installation. + */ +bool BootloaderInstallSansa::install(void) +{ + if(sansa.sectorbuf == nullptr) { + emit logItem(tr("Error: can't allocate buffer memory!"), LOGERROR); + return false; + emit done(true); + } + + emit logItem(tr("Searching for Sansa"), LOGINFO); + + int n = sansa_scan(&sansa); + if(n == -1) { + emit logItem(tr("Permission for disc access denied!\n" + "This is required to install the bootloader"), + LOGERROR); + emit done(true); + return false; + } + if(n == 0) { + emit logItem(tr("No Sansa detected!"), LOGERROR); + emit done(true); + return false; + } + if(sansa.hasoldbootloader) { + emit logItem(tr("OLD ROCKBOX INSTALLATION DETECTED, ABORTING.\n" + "You must reinstall the original Sansa firmware before running\n" + "sansapatcher for the first time.\n" + "See http://www.rockbox.org/wiki/SansaE200Install\n"), + LOGERROR); + emit done(true); + return false; + } + emit logItem(tr("Downloading bootloader file"), LOGINFO); + + downloadBlStart(m_blurl); + connect(this, &BootloaderInstallBase::downloadDone, this, &BootloaderInstallSansa::installStage2); + return true; +} + + +/** Finish bootloader installation. + */ +void BootloaderInstallSansa::installStage2(void) +{ + unsigned char* buf = nullptr; + unsigned int len; + + emit logItem(tr("Installing Rockbox bootloader"), LOGINFO); + QCoreApplication::processEvents(); + if(!sansaInitialize(&sansa)) { + emit done(true); + return; + } + + if(sansa_reopen_rw(&sansa) < 0) { + emit logItem(tr("Could not open Sansa in R/W mode"), LOGERROR); + emit done(true); + return; + } + + // check model -- if sansapatcher reports a c200 don't install an e200 + // bootloader and vice versa. + // The model is available in the mi4 file at offset 0x1fc and matches + // the targetname set by sansapatcher. + emit logItem(tr("Checking downloaded bootloader"), LOGINFO); + m_tempfile.open(); + QString blfile = m_tempfile.fileName(); + char magic[4]; + m_tempfile.seek(0x1fc); + m_tempfile.read(magic, 4); + m_tempfile.close(); + if(memcmp(sansa.targetname, magic, 4) != 0) { + emit logItem(tr("Bootloader mismatch! Aborting."), LOGERROR); + LOG_INFO("Targetname: %s, mi4 magic: %c%c%c%c", + sansa.targetname, magic[0], magic[1], magic[2], magic[3]); + emit done(true); + sansa_close(&sansa); + return; + } + + len = sansa_read_bootloader(&sansa, blfile.toLatin1().data(), &buf); + if(sansa_add_bootloader(&sansa, buf, len) == 0) { + emit logItem(tr("Successfully installed bootloader"), LOGOK); + sansa_close(&sansa); +#if defined(Q_OS_MACX) + m_remountDevice = sansa.diskname; + connect(this, SIGNAL(remounted(bool)), this, SLOT(installStage3(bool))); + waitRemount(); +#else + installStage3(true); +#endif + } + else { + emit logItem(tr("Failed to install bootloader"), LOGERROR); + sansa_close(&sansa); + emit done(true); + return; + } + +} + + +void BootloaderInstallSansa::installStage3(bool mounted) +{ + if(mounted) { + logInstall(LogAdd); + emit logItem(tr("Bootloader Installation complete."), LOGINFO); + emit done(false); + return; + } + else { + emit logItem(tr("Writing log aborted"), LOGERROR); + emit done(true); + } + LOG_INFO() << "version installed:" + << m_blversion.toString(Qt::ISODate); +} + + +/** Uninstall the bootloader. + */ +bool BootloaderInstallSansa::uninstall(void) +{ + emit logItem(tr("Uninstalling bootloader"), LOGINFO); + QCoreApplication::processEvents(); + + if(!sansaInitialize(&sansa)) { + emit done(true); + return false; + } + + if (sansa.hasoldbootloader) { + emit logItem(tr("OLD ROCKBOX INSTALLATION DETECTED, ABORTING.\n" + "You must reinstall the original Sansa firmware before running\n" + "sansapatcher for the first time.\n" + "See http://www.rockbox.org/wiki/SansaE200Install\n"), + LOGERROR); + emit done(true); + return false; + } + + if (sansa_reopen_rw(&sansa) < 0) { + emit logItem(tr("Could not open Sansa in R/W mode"), LOGERROR); + emit done(true); + return false; + } + + if (sansa_delete_bootloader(&sansa)==0) { + emit logItem(tr("Successfully removed bootloader"), LOGOK); + logInstall(LogRemove); + emit logProgress(1, 1); + emit done(false); + sansa_close(&sansa); + return true; + } + else { + emit logItem(tr("Removing bootloader failed."),LOGERROR); + emit done(true); + sansa_close(&sansa); + return false; + } + + return false; +} + + +/** Check if bootloader is already installed + */ +BootloaderInstallBase::BootloaderType BootloaderInstallSansa::installed(void) +{ + int num; + + if(!sansaInitialize(&sansa)) { + return BootloaderUnknown; + } + if((num = sansa_list_images(&sansa)) == 2) { + sansa_close(&sansa); + return BootloaderRockbox; + } + else if(num == 1) { + sansa_close(&sansa); + return BootloaderOther; + } + return BootloaderUnknown; + +} + +bool BootloaderInstallSansa::sansaInitialize(struct sansa_t *sansa) +{ + if(!m_blfile.isEmpty()) { + QString devicename = Utils::resolveDevicename(m_blfile); + if(devicename.isEmpty()) { + emit logItem(tr("Error: could not retrieve device name"), LOGERROR); + return false; + } +#if defined(Q_OS_WIN32) + sprintf(sansa->diskname, "\\\\.\\PhysicalDrive%i", devicename.toInt()); +#elif defined(Q_OS_MACX) + sprintf(sansa->diskname, + "%s", qPrintable(devicename.remove(QRegExp("s[0-9]+$")))); +#else + sprintf(sansa->diskname, + "%s", qPrintable(devicename.remove(QRegExp("[0-9]+$")))); +#endif + LOG_INFO() << "sansapatcher: overriding scan, using" + << sansa->diskname; + } + else if(sansa_scan(sansa) != 1) { + emit logItem(tr("Can't find Sansa"), LOGERROR); + return false; + } + + if (sansa_open(sansa, 0) < 0) { + emit logItem(tr("Could not open Sansa"), LOGERROR); + return false; + } + + if (sansa_read_partinfo(sansa,0) < 0) { + emit logItem(tr("Could not read partition table"), LOGERROR); + sansa_close(sansa); + return false; + } + + int i = is_sansa(sansa); + if(i < 0) { + emit logItem(tr("Disk is not a Sansa (Error %1), aborting.").arg(i), LOGERROR); + sansa_close(sansa); + return false; + } + return true; +} + + +/** Get capabilities of subclass installer. + */ +BootloaderInstallBase::Capabilities BootloaderInstallSansa::capabilities(void) +{ + return (Install | Uninstall | IsRaw | CanCheckInstalled); +} + -- cgit v1.2.3