summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCástor Muñoz <cmvidal@gmail.com>2016-02-05 00:25:31 +0100
committerFranklin Wei <franklin@rockbox.org>2019-10-28 00:09:35 -0400
commite43ef1f3e7630a112378773e0ba9c6c020b2e65f (patch)
treec02dd7f577631810039a7f5a77b7355628cd91a8
parentc353bef3d1902229be40118ce6b52770e5346787 (diff)
downloadrockbox-e43ef1f3e7630a112378773e0ba9c6c020b2e65f.tar.gz
rockbox-e43ef1f3e7630a112378773e0ba9c6c020b2e65f.tar.bz2
rockbox-e43ef1f3e7630a112378773e0ba9c6c020b2e65f.zip
rbutil: add support for iPod Classic 6G bootloader
Change-Id: I0e237a81098a2d4df8d9f5d6deaaab3863a84fc6
-rw-r--r--rbutil/rbutilqt/Makefile.libs4
-rw-r--r--rbutil/rbutilqt/base/bootloaderinstallhelper.cpp4
-rw-r--r--rbutil/rbutilqt/base/bootloaderinstalls5l.cpp428
-rw-r--r--rbutil/rbutilqt/base/bootloaderinstalls5l.h71
-rw-r--r--rbutil/rbutilqt/changelog.txt1
-rw-r--r--rbutil/rbutilqt/progressloggerfrm.ui9
-rw-r--r--rbutil/rbutilqt/rbutil.ini3
-rw-r--r--rbutil/rbutilqt/rbutilqt.pri2
-rw-r--r--rbutil/rbutilqt/rbutilqt.pro2
9 files changed, 519 insertions, 5 deletions
diff --git a/rbutil/rbutilqt/Makefile.libs b/rbutil/rbutilqt/Makefile.libs
index ecb1c1814e..bd0dc121af 100644
--- a/rbutil/rbutilqt/Makefile.libs
+++ b/rbutil/rbutilqt/Makefile.libs
@@ -31,7 +31,7 @@ export CFLAGS=$(EXTRALIB_CFLAGS)
export CC=$(EXTRALIBS_CC)
export AR=$(EXTRALIBS_AR)
-libs: librbspeex libucl libipodpatcher libsansapatcher libmkamsboot libmktccboot libmkmpioboot libchinachippatcher libmkimxboot
+libs: librbspeex libucl libipodpatcher libsansapatcher libmkamsboot libmktccboot libmkmpioboot libchinachippatcher libmkimxboot libmks5lboot
librbspeex:
@@ -61,3 +61,5 @@ libchinachippatcher:
libmkimxboot:
$(SILENT)$(MAKE) -C $(RBBASE_DIR)/rbutil/mkimxboot BUILD_DIR=$(BUILD_DIR)/mkimxboot libmkimxboot.a
+libmks5lboot:
+ $(SILENT)$(MAKE) -C $(RBBASE_DIR)/rbutil/mks5lboot BUILD_DIR=$(BUILD_DIR)/mks5lboot libmks5lboot.a
diff --git a/rbutil/rbutilqt/base/bootloaderinstallhelper.cpp b/rbutil/rbutilqt/base/bootloaderinstallhelper.cpp
index fe962d2b1d..d6d2dbc7a1 100644
--- a/rbutil/rbutilqt/base/bootloaderinstallhelper.cpp
+++ b/rbutil/rbutilqt/base/bootloaderinstallhelper.cpp
@@ -31,6 +31,7 @@
#include "bootloaderinstalltcc.h"
#include "bootloaderinstallmpio.h"
#include "bootloaderinstallimx.h"
+#include "bootloaderinstalls5l.h"
BootloaderInstallBase* BootloaderInstallHelper::createBootloaderInstaller(QObject* parent, QString type)
{
@@ -64,6 +65,9 @@ BootloaderInstallBase* BootloaderInstallHelper::createBootloaderInstaller(QObjec
else if(type == "imx") {
return new BootloaderInstallImx(parent);
}
+ else if(type == "s5l") {
+ return new BootloaderInstallS5l(parent);
+ }
else {
return NULL;
}
diff --git a/rbutil/rbutilqt/base/bootloaderinstalls5l.cpp b/rbutil/rbutilqt/base/bootloaderinstalls5l.cpp
new file mode 100644
index 0000000000..2442970655
--- /dev/null
+++ b/rbutil/rbutilqt/base/bootloaderinstalls5l.cpp
@@ -0,0 +1,428 @@
+/***************************************************************************
+ * __________ __ ___.
+ * 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 <QtCore>
+#include "bootloaderinstallbase.h"
+#include "bootloaderinstalls5l.h"
+#include "Logger.h"
+#include "utils.h"
+#include "system.h"
+#include "rbsettings.h"
+#include "systeminfo.h"
+
+#include "../mks5lboot/mks5lboot.h"
+
+
+BootloaderInstallS5l::BootloaderInstallS5l(QObject *parent)
+ : BootloaderInstallBase(parent)
+{
+}
+
+
+bool BootloaderInstallS5l::install(void)
+{
+ LOG_INFO() << "installing bootloader";
+ doInstall = true;
+ return installStage1();
+}
+
+
+bool BootloaderInstallS5l::uninstall(void)
+{
+ LOG_INFO() << "uninstalling bootloader";
+ doInstall = false;
+ return installStage1();
+}
+
+
+bool BootloaderInstallS5l::installStage1(void)
+{
+ LOG_INFO() << "installStage1";
+
+ mntpoint = RbSettings::value(RbSettings::Mountpoint).toString();
+
+ if (!Utils::mountpoints(Utils::MountpointsSupported).contains(mntpoint)) {
+ LOG_ERROR() << "iPod not mounted:" << mntpoint;
+ emit logItem(tr("Could not find mounted iPod."), LOGERROR);
+ emit done(true);
+ return false;
+ }
+
+ if (doInstall) {
+ // download firmware from server
+ emit logItem(tr("Downloading bootloader file..."), LOGINFO);
+ connect(this, SIGNAL(downloadDone()), this, SLOT(installStageMkdfu()));
+ downloadBlStart(m_blurl);
+ }
+ else {
+ installStageMkdfu();
+ }
+
+ return true;
+}
+
+
+void BootloaderInstallS5l::installStageMkdfu(void)
+{
+ int dfu_type;
+ QString dfu_arg;
+ char errstr[200];
+
+ LOG_INFO() << "installStageMkdfu";
+
+ setProgress(0);
+ aborted = false;
+ connect(this, SIGNAL(installAborted()), this, SLOT(abortInstall()));
+ connect(this, SIGNAL(done(bool)), this, SLOT(installDone(bool)));
+
+ if (doInstall) {
+ dfu_type = DFU_INST;
+ m_tempfile.open();
+ dfu_arg = m_tempfile.fileName();
+ m_tempfile.close();
+ }
+ else {
+ dfu_type = DFU_UNINST;
+ dfu_arg = RbSettings::value(RbSettings::Platform).toString();
+ }
+
+ // build DFU image
+ dfu_buf = mkdfu(dfu_type, dfu_arg.toLocal8Bit().data(),
+ &dfu_size, errstr, sizeof(errstr));
+ if (!dfu_buf) {
+ LOG_ERROR() << "mkdfu() failed:" << errstr;
+ emit logItem(errstr, LOGERROR);
+ emit logItem(tr("Could not make DFU image."), LOGERROR);
+ emit done(true);
+ return;
+ }
+
+ LOG_INFO() << "preparing installStageWaitForEject";
+ emit logItem(tr("Ejecting iPod..."), LOGINFO);
+ setProgress(10);
+ scanTimer = QTime();
+ installStageWaitForEject();
+}
+
+
+void BootloaderInstallS5l::installStageWaitForEject(void)
+{
+ if (!updateProgress())
+ return; /* aborted */
+
+ if (scanTimer.isNull() || (scanTimer.elapsed() > 3000)) {
+ scanSuccess = Utils::ejectDevice(mntpoint);
+ if (!scanSuccess) {
+ scanSuccess = !Utils::mountpoints(
+ Utils::MountpointsSupported).contains(mntpoint);
+ }
+ scanTimer.start();
+ }
+ if (!scanSuccess) {
+ if (!actionShown) {
+ emit logItem(tr("Action required:\n"
+ " Please make sure no programs are accessing\n"
+ " files on the device. If ejecting still fails\n"
+ " please use your computers eject funtionality."),
+ LOGWARNING);
+ actionShown = true;
+ }
+ QTimer::singleShot(250, this, SLOT(installStageWaitForEject()));
+ return;
+ }
+ emit logItem(tr("Device successfully ejected."), LOGINFO);
+
+ LOG_INFO() << "preparing installStageWaitForProcs";
+ setProgress(40, 18);
+ scanTimer = QTime();
+ installStageWaitForProcs();
+}
+
+
+void BootloaderInstallS5l::installStageWaitForProcs(void)
+{
+ if (!updateProgress())
+ return; /* aborted */
+
+ if (scanTimer.isNull() || (scanTimer.elapsed() > 1000)) {
+ scanSuccess = Utils::findRunningProcess(QStringList("iTunes")).isEmpty();
+ scanTimer.start();
+ }
+ if (!scanSuccess) {
+ if (!actionShown) {
+ emit logItem(tr("Action required:\n"
+ " Quit iTunes application."), LOGWARNING);
+ actionShown = true;
+ }
+ QTimer::singleShot(250, this, SLOT(installStageWaitForProcs()));
+ return;
+ }
+ if (actionShown) {
+ emit logItem(tr("iTunes closed."), LOGINFO);
+ if (!updateProgress())
+ return; /* aborted */
+ }
+
+ QList<int> helperPids = Utils::findRunningProcess(
+#if defined(Q_OS_WIN32)
+ QStringList("iTunesHelper"))["iTunesHelper.exe"];
+#else
+ QStringList("iTunesHelper"))["iTunesHelper"];
+#endif
+ suspendedPids = Utils::suspendProcess(helperPids, true);
+ if (suspendedPids.size() != helperPids.size()) {
+ emit logItem(tr("Could not suspend iTunesHelper. Stop it\n"
+ "using the Task Manager, and try again."), LOGERROR);
+ emit done(true);
+ return;
+ }
+
+ LOG_INFO() << "preparing installStageWaitForSpindown";
+ // for Windows: skip waiting if the HDD was ejected a time ago
+ if (progressTimer.elapsed() < progressTimeout)
+ emit logItem(tr("Waiting for HDD spin-down..."), LOGINFO);
+ installStageWaitForSpindown();
+}
+
+
+void BootloaderInstallS5l::installStageWaitForSpindown(void)
+{
+ if (!updateProgress())
+ return; /* aborted */
+
+ if (progressTimer.elapsed() < progressTimeout) {
+ QTimer::singleShot(250, this, SLOT(installStageWaitForSpindown()));
+ return;
+ }
+
+ LOG_INFO() << "preparing installStageWaitForDfu";
+ emit logItem(tr("Waiting for DFU mode..."), LOGINFO);
+ emit logItem(tr("Action required:\n"
+ " Press and hold SELECT+MENU buttons, after\n"
+ " about 12 seconds a new action will require\n"
+ " you to release the buttons, DO IT QUICKLY,\n"
+ " otherwise the process could fail."), LOGWARNING);
+ scanTimer = QTime();
+ installStageWaitForDfu();
+}
+
+
+void BootloaderInstallS5l::installStageWaitForDfu(void)
+{
+ if (!updateProgress())
+ return; /* aborted */
+
+ if (scanTimer.isNull() || (scanTimer.elapsed() > 2000)) {
+ scanSuccess = System::listUsbIds().contains(0x05ac1223);
+ scanTimer.start();
+ }
+ if (!scanSuccess) {
+ QTimer::singleShot(250, this, SLOT(installStageWaitForDfu()));
+ return;
+ }
+ emit logItem(tr("DFU mode detected."), LOGINFO);
+
+ emit logItem(tr("Action required:\n"
+ " Release SELECT+MENU buttons and wait..."), LOGWARNING);
+
+ // Once the iPod enters DFU mode, the device will reset again if
+ // SELECT+MENU remains pressed for another 8 seconds. To avoid a
+ // reset while the NOR is being written, we wait ~10 seconds
+ // before sending the DFU image.
+ LOG_INFO() << "preparing installStageSendDfu";
+ setProgress(60, 10);
+ installStageSendDfu();
+}
+
+
+void BootloaderInstallS5l::installStageSendDfu(void)
+{
+ if (!updateProgress())
+ return; /* aborted */
+
+ if (progressTimer.elapsed() < progressTimeout) {
+ QTimer::singleShot(250, this, SLOT(installStageSendDfu()));
+ return;
+ }
+
+ if (!System::listUsbIds().contains(0x05ac1223)) {
+ LOG_ERROR() << "device not in DFU mode";
+ emit logItem(tr("Device is not in DFU mode. It seems that\n"
+ "the previous required action failed, please\n"
+ "try again."), LOGERROR);
+ emit done(true);
+ return;
+ }
+
+ emit logItem(tr("Transfering DFU image..."), LOGINFO);
+ if (!updateProgress())
+ return; /* aborted */
+
+ char errstr[200];
+ if (!ipoddfu_send(0x1223, dfu_buf, dfu_size, errstr, sizeof(errstr))) {
+ LOG_ERROR() << "ipoddfu_send() failed:" << errstr;
+#if defined(Q_OS_WIN32)
+ if (strstr(errstr, "DFU device not found"))
+ {
+ emit logItem(tr("No valid DFU USB driver found.\n"
+ "Install iTunes (or the Apple Device Driver)\n"
+ "and try again."),
+ LOGERROR);
+ }
+ else
+#endif
+ {
+ emit logItem(errstr, LOGERROR);
+ emit logItem(tr("Could not transfer DFU image."), LOGERROR);
+ }
+ emit done(true);
+ return;
+ }
+ emit logItem(tr("DFU transfer completed."), LOGINFO);
+
+ LOG_INFO() << "preparing installStageWaitForRemount";
+ emit logItem(tr("Restarting iPod, waiting for remount..."), LOGINFO);
+ setProgress(99, 45);
+ scanTimer = QTime();
+ installStageWaitForRemount();
+}
+
+
+void BootloaderInstallS5l::installStageWaitForRemount(void)
+{
+ if (!updateProgress())
+ return; /* aborted */
+
+ if (scanTimer.isNull() || (scanTimer.elapsed() > 5000)) {
+ scanSuccess = Utils::mountpoints(
+ Utils::MountpointsSupported).contains(mntpoint);
+ scanTimer.start();
+ }
+ if (!scanSuccess) {
+ if (!actionShown && (progressTimer.elapsed() > progressTimeout)) {
+ emit logItem(tr("Action required:\n"
+ " Could not remount the device, try to do it\n"
+ " manually. If the iPod didn't restart, force\n"
+ " a reset by pressing SELECT+MENU buttons\n"
+ " for about 5 seconds. If the problem could\n"
+ " not be solved then click 'Abort' to cancel."),
+ LOGWARNING);
+ actionShown = true;
+ }
+ QTimer::singleShot(250, this, SLOT(installStageWaitForRemount()));
+ return;
+ }
+ emit logItem(tr("Device remounted."), LOGINFO);
+
+ emit logItem(tr("Bootloader successfully %1.").
+ arg(tr(doInstall ? "installed" : "uninstalled")), LOGOK);
+
+ logInstall(doInstall ? LogAdd : LogRemove);
+ emit logProgress(1, 1);
+ emit done(false);
+}
+
+
+void BootloaderInstallS5l::installDone(bool status)
+{
+ LOG_INFO() << "installDone, status:" << status;
+ if (Utils::suspendProcess(suspendedPids, false).size() != suspendedPids.size())
+ emit logItem(tr("Could not resume iTunesHelper."), LOGWARNING);
+}
+
+
+void BootloaderInstallS5l::abortInstall(void)
+{
+ LOG_INFO() << "abortInstall";
+ aborted = true;
+ disconnect(this, SIGNAL(installAborted()), this, SLOT(abortInstall()));
+}
+
+
+bool BootloaderInstallS5l::abortDetected(void)
+{
+ if (aborted) {
+ LOG_ERROR() << "abortDetected";
+ emit logItem(tr("%1 aborted by user.").
+ arg(tr(doInstall ? "Install" : "Uninstall")), LOGERROR);
+ emit done(true);
+ return true;
+ }
+ return false;
+}
+
+
+void BootloaderInstallS5l::setProgress(int progress, int secondsTimeout)
+{
+ progressTimer.start();
+ progressTimeout = secondsTimeout * 1000;
+ progOrigin = progTarget;
+ progTarget = progress;
+ actionShown = false;
+}
+
+
+bool BootloaderInstallS5l::updateProgress(void)
+{
+ if (progressTimeout) {
+ progCurrent = qMin(progTarget, progOrigin +
+ progressTimer.elapsed()*(progTarget-progOrigin)/progressTimeout);
+ }
+ else {
+ progCurrent = progTarget;
+ }
+ emit logProgress(progCurrent, 100);
+ QCoreApplication::sendPostedEvents();
+ QCoreApplication::processEvents();
+ return !abortDetected();
+}
+
+
+BootloaderInstallBase::BootloaderType BootloaderInstallS5l::installed(void)
+{
+ bool rbblInstalled;
+
+ QString device = Utils::resolveDevicename(m_blfile);
+ if (device.isEmpty()) {
+ LOG_INFO() << "installed: BootloaderUnknown";
+ return BootloaderUnknown;
+ }
+
+ // rely on logfile
+ QString logfile = RbSettings::value(RbSettings::Mountpoint).toString()
+ + "/.rockbox/rbutil.log";
+ QSettings s(logfile, QSettings::IniFormat, this);
+ QString section = SystemInfo::value(
+ SystemInfo::CurBootloaderName).toString().section('/', -1);
+ rbblInstalled = s.contains("Bootloader/" + section);
+
+ if (rbblInstalled) {
+ LOG_INFO() << "installed: BootloaderRockbox";
+ return BootloaderRockbox;
+ }
+ else {
+ LOG_INFO() << "installed: BootloaderOther";
+ return BootloaderOther;
+ }
+}
+
+
+BootloaderInstallBase::Capabilities BootloaderInstallS5l::capabilities(void)
+{
+ return (Install | Uninstall);
+}
diff --git a/rbutil/rbutilqt/base/bootloaderinstalls5l.h b/rbutil/rbutilqt/base/bootloaderinstalls5l.h
new file mode 100644
index 0000000000..a59e5d378b
--- /dev/null
+++ b/rbutil/rbutilqt/base/bootloaderinstalls5l.h
@@ -0,0 +1,71 @@
+/***************************************************************************
+ * __________ __ ___.
+ * 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.
+ *
+ ****************************************************************************/
+
+#ifndef BOOTLOADERINSTALLS5L_H
+#define BOOTLOADERINSTALLS5L_H
+
+#include <QtCore>
+#include "bootloaderinstallbase.h"
+
+
+//! bootloader installation derivate based on mks5lboot
+class BootloaderInstallS5l : public BootloaderInstallBase
+{
+ Q_OBJECT
+
+ public:
+ BootloaderInstallS5l(QObject *parent);
+ bool install(void);
+ bool uninstall(void);
+ BootloaderInstallBase::BootloaderType installed(void);
+ Capabilities capabilities(void);
+
+ private slots:
+ bool installStage1(void);
+ void installStageMkdfu(void);
+ void installStageWaitForEject(void);
+ void installStageWaitForSpindown(void);
+ void installStageWaitForProcs(void);
+ void installStageWaitForDfu(void);
+ void installStageSendDfu(void);
+ void installStageWaitForRemount(void);
+ void abortInstall(void);
+ void installDone(bool);
+
+ private:
+ bool doInstall;
+ QString mntpoint;
+ unsigned char* dfu_buf;
+ int dfu_size;
+ QList<int> suspendedPids;
+ bool aborted;
+ bool abortDetected(void);
+ QTime scanTimer;
+ bool scanSuccess;
+ // progress
+ QTime progressTimer;
+ int progressTimeout;
+ int progCurrent;
+ int progOrigin;
+ int progTarget;
+ bool actionShown;
+ void setProgress(int, int=0);
+ bool updateProgress(void);
+};
+
+#endif
diff --git a/rbutil/rbutilqt/changelog.txt b/rbutil/rbutilqt/changelog.txt
index c97105f651..0dec314155 100644
--- a/rbutil/rbutilqt/changelog.txt
+++ b/rbutil/rbutilqt/changelog.txt
@@ -25,3 +25,4 @@ Version 1.4.1
* Extend hint when uninstallation requires reinstalling the Original Firmware.
* Improve update check information dialog.
* Correct USB IDs for Sandisk Sansa c200v2.
+* Add support for iPod Classic 6G bootloader.
diff --git a/rbutil/rbutilqt/progressloggerfrm.ui b/rbutil/rbutilqt/progressloggerfrm.ui
index c10e26a4af..cc4509081a 100644
--- a/rbutil/rbutilqt/progressloggerfrm.ui
+++ b/rbutil/rbutilqt/progressloggerfrm.ui
@@ -5,8 +5,13 @@
<rect>
<x>0</x>
<y>0</y>
- <width>315</width>
- <height>302</height>
+ <!-- Larger progress window - quick workaround to avoid user confusion
+ during iPod Classic 6G bootloader installation. Due to progress
+ scroll, many users (including me) are confused and do not realize
+ an important action message.
+ -->
+ <width>360</width>
+ <height>560</height>
</rect>
</property>
<property name="windowTitle" >
diff --git a/rbutil/rbutilqt/rbutil.ini b/rbutil/rbutilqt/rbutil.ini
index e8ec8afb25..06dc622864 100644
--- a/rbutil/rbutilqt/rbutil.ini
+++ b/rbutil/rbutilqt/rbutil.ini
@@ -362,7 +362,8 @@ encoder=rbspeex
[ipod6g]
name="Ipod Classic (6th gen)"
buildserver_modelname=ipod6g
-bootloadermethod=none
+bootloadermethod=s5l
+bootloadername=/ipod/bootloader-ipod6g.ipod
manualname=
brand=Apple
usbid=0x05ac1261
diff --git a/rbutil/rbutilqt/rbutilqt.pri b/rbutil/rbutilqt/rbutilqt.pri
index 9f1aea694d..d9ef1071f4 100644
--- a/rbutil/rbutilqt/rbutilqt.pri
+++ b/rbutil/rbutilqt/rbutilqt.pri
@@ -66,6 +66,7 @@ SOURCES += \
base/bootloaderinstalltcc.cpp \
base/bootloaderinstallmpio.cpp \
base/bootloaderinstallimx.cpp \
+ base/bootloaderinstalls5l.cpp \
base/rockboxinfo.cpp \
../../tools/mkboot.c \
../../tools/iriver.c \
@@ -142,6 +143,7 @@ HEADERS += \
base/bootloaderinstalltcc.h \
base/bootloaderinstallmpio.h \
base/bootloaderinstallimx.h \
+ base/bootloaderinstalls5l.h \
base/rockboxinfo.h \
../../tools/mkboot.h \
../../tools/iriver.h \
diff --git a/rbutil/rbutilqt/rbutilqt.pro b/rbutil/rbutilqt/rbutilqt.pro
index 745d9887b5..cfd6fb39ab 100644
--- a/rbutil/rbutilqt/rbutilqt.pro
+++ b/rbutil/rbutilqt/rbutilqt.pro
@@ -88,7 +88,7 @@ extralibs.commands = $$SILENT \
# Note: order is important for RBLIBS! The libs are appended to the linker
# flags in this order, put libucl at the end.
RBLIBS = rbspeex ipodpatcher sansapatcher mkamsboot mktccboot \
- mkmpioboot chinachippatcher mkimxboot ucl
+ mkmpioboot chinachippatcher mkimxboot mks5lboot ucl
!win32-msvc* {
QMAKE_EXTRA_TARGETS += extralibs
PRE_TARGETDEPS += extralibs