When detecting a macpod cancel bootloader installation. Add a link to IpodConverstion...
[Rockbox.git] / rbutil / rbutilqt / installbootloader.cpp
blobd252ebbcc79153e951a9ca35380ee6cedbc8d261
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
9 * Copyright (C) 2007 by Dominik Wenger
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 "installbootloader.h"
21 #include "irivertools/checksums.h"
23 BootloaderInstaller::BootloaderInstaller(QObject* parent): QObject(parent)
28 void BootloaderInstaller::install(ProgressloggerInterface* dp)
30 m_dp = dp;
31 m_install = true;
32 m_dp->addItem(tr("Starting bootloader installation"),LOGINFO);
33 connect(this, SIGNAL(done(bool)), this, SLOT(installEnded(bool)));
35 if(m_bootloadermethod == "gigabeatf")
37 // connect internal signal
38 connect(this,SIGNAL(prepare()),this,SLOT(gigabeatPrepare()));
39 connect(this,SIGNAL(finish()),this,SLOT(gigabeatFinish()));
41 else if(m_bootloadermethod == "iaudio")
43 // connect internal signal
44 connect(this,SIGNAL(prepare()),this,SLOT(iaudioPrepare()));
45 connect(this,SIGNAL(finish()),this,SLOT(iaudioFinish()));
47 else if(m_bootloadermethod == "h10")
49 // connect internal signal
50 connect(this,SIGNAL(prepare()),this,SLOT(h10Prepare()));
51 connect(this,SIGNAL(finish()),this,SLOT(h10Finish()));
53 else if(m_bootloadermethod == "ipodpatcher")
55 // connect internal signal
56 connect(this,SIGNAL(prepare()),this,SLOT(ipodPrepare()));
57 connect(this,SIGNAL(finish()),this,SLOT(ipodFinish()));
59 else if(m_bootloadermethod == "sansapatcher")
61 // connect internal signal
62 connect(this,SIGNAL(prepare()),this,SLOT(sansaPrepare()));
63 connect(this,SIGNAL(finish()),this,SLOT(sansaFinish()));
65 else if(m_bootloadermethod == "fwpatcher")
67 // connect internal signal
68 connect(this,SIGNAL(prepare()),this,SLOT(iriverPrepare()));
69 connect(this,SIGNAL(finish()),this,SLOT(iriverFinish()));
71 else
73 m_dp->addItem(tr("unsupported install Method"),LOGERROR);
74 emit done(true);
75 return;
78 emit prepare();
81 void BootloaderInstaller::uninstall(ProgressloggerInterface* dp)
83 m_dp = dp;
84 m_install = false;
85 m_dp->addItem(tr("Starting bootloader uninstallation"),LOGINFO);
86 connect(this, SIGNAL(done(bool)), this, SLOT(installEnded(bool)));
88 if(m_bootloadermethod == "gigabeatf")
90 // connect internal signal
91 connect(this,SIGNAL(prepare()),this,SLOT(gigabeatPrepare()));
93 else if(m_bootloadermethod == "iaudio")
95 m_dp->addItem(tr("No uninstallation possible"),LOGWARNING);
96 emit done(true);
97 return;
99 else if(m_bootloadermethod == "iaudio")
101 // connect internal signal
102 connect(this,SIGNAL(prepare()),this,SLOT(h10Prepare()));
104 else if(m_bootloadermethod == "ipodpatcher")
106 // connect internal signal
107 connect(this,SIGNAL(prepare()),this,SLOT(ipodPrepare()));
109 else if(m_bootloadermethod == "sansapatcher")
111 // connect internal signal
112 connect(this,SIGNAL(prepare()),this,SLOT(sansaPrepare()));
114 else if(m_bootloadermethod == "fwpatcher")
116 m_dp->addItem(tr("No uninstallation possible"),LOGWARNING);
117 emit done(true);
118 return;
120 else
122 m_dp->addItem(tr("unsupported install Method"),LOGERROR);
123 emit done(true);
124 return;
127 emit prepare();
130 void BootloaderInstaller::downloadRequestFinished(int id, bool error)
132 qDebug() << "BootloaderInstall::downloadRequestFinished" << id << error;
133 qDebug() << "error:" << getter->errorString();
135 downloadDone(error);
138 void BootloaderInstaller::downloadDone(bool error)
140 qDebug() << "Install::downloadDone, error:" << error;
142 // update progress bar
144 int max = m_dp->getProgressMax();
145 if(max == 0) {
146 max = 100;
147 m_dp->setProgressMax(max);
149 m_dp->setProgressValue(max);
150 if(getter->httpResponse() != 200) {
151 m_dp->addItem(tr("Download error: received HTTP error %1.").arg(getter->httpResponse()),LOGERROR);
152 m_dp->abort();
153 emit done(true);
154 return;
156 if(error) {
157 m_dp->addItem(tr("Download error: %1").arg(getter->errorString()),LOGERROR);
158 m_dp->abort();
159 emit done(true);
160 return;
162 else m_dp->addItem(tr("Download finished."),LOGOK);
164 emit finish();
168 void BootloaderInstaller::updateDataReadProgress(int read, int total)
170 m_dp->setProgressMax(total);
171 m_dp->setProgressValue(read);
172 qDebug() << "progress:" << read << "/" << total;
176 void BootloaderInstaller::installEnded(bool error)
178 (void) error;
179 m_dp->abort();
182 bool BootloaderInstaller::downloadInfo()
184 // try to get the current build information
185 infodownloader = new HttpGet(this);
187 connect(infodownloader, SIGNAL(done(bool)), this, SLOT(infoDownloadDone(bool)));
188 connect(infodownloader, SIGNAL(requestFinished(int, bool)), this, SLOT(infoRequestFinished(int, bool)));
190 infodownloader->setProxy(m_proxy);
192 qDebug() << "downloading bootloader info";
193 infodownloader->setFile(&bootloaderInfo);
194 infodownloader->getFile(QUrl(m_bootloaderinfoUrl));
196 // block until its downloaded
197 qDebug() << "Waiting for Download finished";
198 infoDownloaded=false;
199 infoError = false;
200 while(!infoDownloaded )
201 QApplication::processEvents();
202 return !infoError;
205 void BootloaderInstaller::infoDownloadDone(bool error)
207 if(error)
209 qDebug() << "network error:" << infodownloader->error();
210 return;
212 qDebug() << "network status:" << infodownloader->error();
214 infoDownloaded = true;
217 void BootloaderInstaller::infoRequestFinished(int id, bool error)
220 if(error)
222 QString errorString;
223 errorString = tr("Network error: %1. Please check your network and proxy settings.")
224 .arg(infodownloader->errorString());
225 if(error) QMessageBox::about(NULL, "Network Error", errorString);
226 qDebug() << "downloadDone:" << id << error;
228 infoError = true;
229 infoDownloaded = true;
231 qDebug() << "infoRequestFinished:" << id << error;
235 void BootloaderInstaller::createInstallLog()
237 m_dp->addItem(tr("Creating installation log"),LOGINFO);
238 QSettings installlog(m_mountpoint + "/.rockbox/rbutil.log", QSettings::IniFormat, 0);
240 bootloaderInfo.open();
241 QSettings info(bootloaderInfo.fileName(), QSettings::IniFormat, this);
242 bootloaderInfo.close();
243 info.beginGroup(m_device);
245 installlog.beginGroup("Bootloader");
246 installlog.setValue("md5sum",info.value("md5sum").toString());
247 installlog.endGroup();
248 installlog.sync();
251 void BootloaderInstaller::removeInstallLog()
253 m_dp->addItem(tr("Editing installation log"),LOGINFO);
254 QSettings installlog(m_mountpoint + "/.rockbox/rbutil.log", QSettings::IniFormat, 0);
255 installlog.beginGroup("Bootloader");
256 installlog.remove("md5sum");
257 installlog.endGroup();
258 installlog.sync();
262 bool BootloaderInstaller::uptodate()
264 QString installedMd5;
265 QString serverMd5;
267 QSettings installlog(m_mountpoint + "/.rockbox/rbutil.log", QSettings::IniFormat, 0);
268 installlog.beginGroup("Bootloader");
269 installedMd5 = installlog.value("md5sum").toString();
270 installlog.endGroup();
272 bootloaderInfo.open();
273 QSettings info(bootloaderInfo.fileName(), QSettings::IniFormat, this);
274 bootloaderInfo.close();
275 info.beginGroup(m_device);
276 serverMd5 = info.value("md5sum").toString();
277 info.endGroup();
279 if(installedMd5 != serverMd5)
280 return false;
281 else
282 return true;
285 /**************************************************
286 *** gigabeat secific code
287 ***************************************************/
289 void BootloaderInstaller::gigabeatPrepare()
291 if(m_install) // Installation
293 QString url = m_bootloaderUrlBase + "/gigabeat/" + m_bootloadername;
295 m_dp->addItem(tr("Downloading file %1.%2")
296 .arg(QFileInfo(url).baseName(), QFileInfo(url).completeSuffix()),LOGINFO);
298 // temporary file needs to be opened to get the filename
299 downloadFile.open();
300 m_tempfilename = downloadFile.fileName();
301 downloadFile.close();
302 // get the real file.
303 getter = new HttpGet(this);
304 getter->setProxy(m_proxy);
305 getter->setFile(&downloadFile);
306 getter->getFile(QUrl(url));
307 // connect signals from HttpGet
308 connect(getter, SIGNAL(done(bool)), this, SLOT(downloadDone(bool)));
309 connect(getter, SIGNAL(dataReadProgress(int, int)), this, SLOT(updateDataReadProgress(int, int)));
310 connect(m_dp, SIGNAL(aborted()), getter, SLOT(abort()));
312 else //UnInstallation
314 QString firmware = m_mountpoint + "/GBSYSTEM/FWIMG/FWIMG01.DAT";
315 QString firmwareOrig = firmware.append(".ORIG");
317 QFileInfo firmwareOrigFI(firmwareOrig);
319 // check if original firmware exists
320 if(!firmwareOrigFI.exists())
322 m_dp->addItem(tr("Could not find the Original Firmware at: %1")
323 .arg(firmwareOrig),LOGERROR);
324 emit done(true);
325 return;
328 QFile firmwareFile(firmware);
329 QFile firmwareOrigFile(firmwareOrig);
331 //remove modified firmware
332 if(!firmwareFile.remove())
334 m_dp->addItem(tr("Could not remove the Firmware at: %1")
335 .arg(firmware),LOGERROR);
336 emit done(true);
337 return;
340 //copy original firmware
341 if(!firmwareOrigFile.copy(firmware))
343 m_dp->addItem(tr("Could not copy the Firmware from: %1 to %2")
344 .arg(firmwareOrig,firmware),LOGERROR);
345 emit done(true);
346 return;
349 removeInstallLog();
351 emit done(false); //success
356 void BootloaderInstaller::gigabeatFinish()
358 // this step is only need for installation, so no code for uninstall here
360 m_dp->addItem(tr("Finishing bootloader install"),LOGINFO);
362 QString firmware = m_mountpoint + "/GBSYSTEM/FWIMG/" + m_bootloadername;
364 QFileInfo firmwareFI(firmware);
366 // check if firmware exists
367 if(!firmwareFI.exists())
369 m_dp->addItem(tr("Could not find the Firmware at: %1")
370 .arg(firmware),LOGERROR);
371 emit done(true);
372 return;
375 QString firmwareOrig = firmware;
376 firmwareOrig.append(".ORIG");
377 QFileInfo firmwareOrigFI(firmwareOrig);
379 // rename the firmware, if there is no original firmware there
380 if(!firmwareOrigFI.exists())
382 QFile firmwareFile(firmware);
383 if(!firmwareFile.rename(firmwareOrig))
385 m_dp->addItem(tr("Could not rename: %1 to %2")
386 .arg(firmware,firmwareOrig),LOGERROR);
387 emit done(true);
388 return;
391 else // or remove the normal firmware, if the original is there
393 QFile firmwareFile(firmware);
394 firmwareFile.remove();
397 //copy the firmware
398 if(!downloadFile.copy(firmware))
400 m_dp->addItem(tr("Could not copy: %1 to %2")
401 .arg(m_tempfilename,firmware),LOGERROR);
402 emit done(true);
403 return;
406 downloadFile.remove();
408 createInstallLog();
410 m_dp->addItem(tr("Bootloader install finished successfully."),LOGOK);
411 m_dp->addItem(tr("To finish the Bootloader installation, follow the steps below."),LOGINFO);
412 m_dp->addItem(tr("1. Eject/Unmount your Device."),LOGINFO);
413 m_dp->addItem(tr("2. Unplug USB and any Power adapters."),LOGINFO);
414 m_dp->addItem(tr("3. Hold POWER to turn the Device off."),LOGINFO);
415 m_dp->addItem(tr("4. Toggle the Battery switch on the Device."),LOGINFO);
416 m_dp->addItem(tr("5. Hold POWER to boot the Rockbox bootloader."),LOGINFO);
419 m_dp->abort();
421 emit done(false); // success
425 /**************************************************
426 *** iaudio secific code
427 ***************************************************/
428 void BootloaderInstaller::iaudioPrepare()
431 QString url = m_bootloaderUrlBase + "/iaudio/" + m_bootloadername;
433 m_dp->addItem(tr("Downloading file %1.%2")
434 .arg(QFileInfo(url).baseName(), QFileInfo(url).completeSuffix()),LOGINFO);
436 // temporary file needs to be opened to get the filename
437 downloadFile.open();
438 m_tempfilename = downloadFile.fileName();
439 downloadFile.close();
440 // get the real file.
441 getter = new HttpGet(this);
442 getter->setProxy(m_proxy);
443 getter->setFile(&downloadFile);
444 getter->getFile(QUrl(url));
445 // connect signals from HttpGet
446 connect(getter, SIGNAL(done(bool)), this, SLOT(downloadDone(bool)));
447 connect(getter, SIGNAL(dataReadProgress(int, int)), this, SLOT(updateDataReadProgress(int, int)));
448 connect(m_dp, SIGNAL(aborted()), getter, SLOT(abort()));
451 void BootloaderInstaller::iaudioFinish()
453 QString firmware = m_mountpoint + "/FIRMWARE/" + m_bootloadername;
455 //copy the firmware
456 if(!downloadFile.copy(firmware))
458 m_dp->addItem(tr("Could not copy: %1 to %2")
459 .arg(m_tempfilename,firmware),LOGERROR);
460 emit done(true);
461 return;
464 downloadFile.remove();
466 createInstallLog();
468 m_dp->addItem(tr("Bootloader install finished successfully."),LOGOK);
469 m_dp->addItem(tr("To finish the Bootloader installation, follow the steps below."),LOGINFO);
470 m_dp->addItem(tr("1. Eject/Unmount your Device."),LOGINFO);
471 m_dp->addItem(tr("2. Turn you Device OFF."),LOGINFO);
472 m_dp->addItem(tr("3. Insert Charger."),LOGINFO);
474 m_dp->abort();
476 emit done(false); // success
481 /**************************************************
482 *** h10 secific code
483 ***************************************************/
484 void BootloaderInstaller::h10Prepare()
486 if(m_install) // Installation
488 QString url = m_bootloaderUrlBase + "/iriver/" + m_bootloadername;
490 m_dp->addItem(tr("Downloading file %1.%2")
491 .arg(QFileInfo(url).baseName(), QFileInfo(url).completeSuffix()),LOGINFO);
493 // temporary file needs to be opened to get the filename
494 downloadFile.open();
495 m_tempfilename = downloadFile.fileName();
496 downloadFile.close();
497 // get the real file.
498 getter = new HttpGet(this);
499 getter->setProxy(m_proxy);
500 getter->setFile(&downloadFile);
501 getter->getFile(QUrl(url));
502 // connect signals from HttpGet
503 connect(getter, SIGNAL(done(bool)), this, SLOT(downloadDone(bool)));
504 connect(getter, SIGNAL(dataReadProgress(int, int)), this, SLOT(updateDataReadProgress(int, int)));
505 connect(m_dp, SIGNAL(aborted()), getter, SLOT(abort()));
507 else // Uninstallation
510 QString firmwarename = m_bootloadername.section('/', -1);
512 QString firmware = m_mountpoint + "/SYSTEM/" + firmwarename;
513 QString firmwareOrig = m_mountpoint + "/SYSTEM/Original.mi4";
515 QFileInfo firmwareFI(firmware);
516 if(!firmwareFI.exists()) //Firmware dosent exists on player
518 firmware = m_mountpoint + "/SYSTEM/H10EMP.mi4"; //attempt other firmwarename
519 firmwareFI.setFile(firmware);
520 if(!firmwareFI.exists()) //Firmware dosent exists on player
522 m_dp->addItem(tr("Firmware does not exist: %1")
523 .arg(firmware),LOGERROR);
524 emit done(true);
525 return;
529 QFileInfo firmwareOrigFI(firmwareOrig);
530 if(!firmwareOrigFI.exists()) //Original Firmware dosent exists on player
532 m_dp->addItem(tr("Original Firmware does not exist: %1")
533 .arg(firmwareOrig),LOGERROR);
534 emit done(true);
535 return;
538 QFile firmwareFile(firmware);
539 QFile firmwareOrigFile(firmwareOrig);
541 //remove modified firmware
542 if(!firmwareFile.remove())
544 m_dp->addItem(tr("Could not remove the Firmware at: %1")
545 .arg(firmware),LOGERROR);
546 emit done(true);
547 return;
550 //copy original firmware
551 if(!firmwareOrigFile.copy(firmware))
553 m_dp->addItem(tr("Could not copy the Firmware from: %1 to %2")
554 .arg(firmwareOrig,firmware),LOGERROR);
555 emit done(true);
556 return;
559 removeInstallLog();
561 emit done(false); //success
566 void BootloaderInstaller::h10Finish()
568 QString firmwarename = m_bootloadername.section('/', -1);
570 QString firmware = m_mountpoint + "/SYSTEM/" + firmwarename;
571 QString firmwareOrig = m_mountpoint + "/SYSTEM/Original.mi4";
573 QFileInfo firmwareFI(firmware);
575 if(!firmwareFI.exists()) //Firmware dosent exists on player
577 firmware = m_mountpoint + "/SYSTEM/H10EMP.mi4"; //attempt other firmwarename
578 firmwareFI.setFile(firmware);
579 if(!firmwareFI.exists()) //Firmware dosent exists on player
581 m_dp->addItem(tr("Firmware does not exist: %1")
582 .arg(firmware),LOGERROR);
583 emit done(true);
584 return;
588 QFileInfo firmwareOrigFI(firmwareOrig);
590 if(!firmwareOrigFI.exists()) //there is already a original firmware
592 QFile firmwareFile(firmware);
593 if(!firmwareFile.rename(firmwareOrig)) //rename Firmware to Original
595 m_dp->addItem(tr("Could not rename: %1 to %2")
596 .arg(firmware,firmwareOrig),LOGERROR);
597 emit done(true);
598 return;
601 else
603 QFile firmwareFile(firmware);
604 firmwareFile.remove();
606 //copy the firmware
607 if(!downloadFile.copy(firmware))
609 m_dp->addItem(tr("Could not copy: %1 to %2")
610 .arg(m_tempfilename,firmware),LOGERROR);
611 emit done(true);
612 return;
615 downloadFile.remove();
617 createInstallLog();
619 m_dp->addItem(tr("Bootloader install finished successfully."),LOGOK);
620 m_dp->abort();
622 emit done(false); // success
626 /**************************************************
627 *** ipod secific code
628 ***************************************************/
629 int verbose =0;
630 // reserves memory for ipodpatcher
631 bool initIpodpatcher()
633 if (ipod_alloc_buffer(&sectorbuf,BUFFER_SIZE) < 0) return true;
634 else return false;
637 void BootloaderInstaller::ipodPrepare()
639 m_dp->addItem(tr("Searching for ipods"),LOGINFO);
640 struct ipod_t ipod;
642 int n = ipod_scan(&ipod);
643 if (n == 0)
645 m_dp->addItem(tr("No Ipods found"),LOGERROR);
646 emit done(true);
647 return;
649 if (n > 1)
651 m_dp->addItem(tr("Too many Ipods found"),LOGERROR);
652 emit done(true);
655 if(m_install) // Installation
658 QString url = m_bootloaderUrlBase + "/ipod/bootloader-" + m_bootloadername + ".ipod";
660 m_dp->addItem(tr("Downloading file %1.%2")
661 .arg(QFileInfo(url).baseName(), QFileInfo(url).completeSuffix()),LOGINFO);
663 // temporary file needs to be opened to get the filename
664 downloadFile.open();
665 m_tempfilename = downloadFile.fileName();
666 downloadFile.close();
667 // get the real file.
668 getter = new HttpGet(this);
669 getter->setProxy(m_proxy);
670 getter->setFile(&downloadFile);
671 getter->getFile(QUrl(url));
672 // connect signals from HttpGet
673 connect(getter, SIGNAL(done(bool)), this, SLOT(downloadDone(bool)));
674 connect(getter, SIGNAL(dataReadProgress(int, int)), this, SLOT(updateDataReadProgress(int, int)));
675 connect(m_dp, SIGNAL(aborted()), getter, SLOT(abort()));
677 else // Uninstallation
679 if (ipod_open(&ipod, 0) < 0)
681 m_dp->addItem(tr("could not open ipod"),LOGERROR);
682 emit done(true);
683 return;
686 if (read_partinfo(&ipod,0) < 0)
688 m_dp->addItem(tr("could not read partitiontable"),LOGERROR);
689 emit done(true);
690 return;
693 if (ipod.pinfo[0].start==0)
695 m_dp->addItem(tr("No partition 0 on disk"),LOGERROR);
697 int i;
698 double sectors_per_MB = (1024.0*1024.0)/ipod.sector_size;
699 m_dp->addItem(tr("[INFO] Part Start Sector End Sector Size (MB) Type\n"),LOGINFO);
700 for ( i = 0; i < 4; i++ )
702 if (ipod.pinfo[i].start != 0)
704 m_dp->addItem(tr("[INFO] %1 %2 %3 %4 %5 (%6)").arg(
705 i).arg(
706 ipod.pinfo[i].start).arg(
707 ipod.pinfo[i].start+ipod.pinfo[i].size-1).arg(
708 ipod.pinfo[i].size/sectors_per_MB).arg(
709 get_parttype(ipod.pinfo[i].type)).arg(
710 ipod.pinfo[i].type),LOGINFO);
713 emit done(true);
714 return;
717 read_directory(&ipod);
719 if (ipod.nimages <= 0)
721 m_dp->addItem(tr("Failed to read firmware directory"),LOGERROR);
722 emit done(true);
723 return;
725 if (getmodel(&ipod,(ipod.ipod_directory[0].vers>>8)) < 0)
727 m_dp->addItem(tr("Unknown version number in firmware (%1)").arg(
728 ipod.ipod_directory[0].vers),LOGERROR);
729 emit done(true);
730 return;
733 if (ipod.macpod)
735 m_dp->addItem(tr("Warning this is a MacPod, Rockbox doesnt work on "
736 "this. Convert it to WinPod\n"
737 "See http://www.rockbox.org/wiki/IpodConverstionToFAT32"),
738 LOGWARNING);
739 emit done(true);
740 return;
743 if (ipod_reopen_rw(&ipod) < 0)
745 m_dp->addItem(tr("Could not open Ipod in RW mode"),LOGERROR);
746 emit done(true);
747 return;
750 if (ipod.ipod_directory[0].entryOffset==0) {
751 m_dp->addItem(tr("No bootloader detected."),LOGERROR);
752 emit done(true);
753 return;
756 if (delete_bootloader(&ipod)==0)
758 m_dp->addItem(tr("Successfully removed Bootloader"),LOGOK);
759 removeInstallLog();
760 emit done(false);
761 ipod_close(&ipod);
762 return;
764 else
766 m_dp->addItem(tr("--delete-bootloader failed."),LOGERROR);
767 emit done(true);
768 ipod_close(&ipod);
769 return;
774 void BootloaderInstaller::ipodFinish()
776 struct ipod_t ipod;
777 ipod_scan(&ipod);
779 if (ipod_open(&ipod, 0) < 0)
781 m_dp->addItem(tr("could not open ipod"),LOGERROR);
782 emit done(true);
783 return;
786 if (read_partinfo(&ipod,0) < 0)
788 m_dp->addItem(tr("could not read partitiontable"),LOGERROR);
789 emit done(true);
790 return;
793 if (ipod.pinfo[0].start==0)
795 m_dp->addItem(tr("No partition 0 on disk"),LOGERROR);
797 int i;
798 double sectors_per_MB = (1024.0*1024.0)/ipod.sector_size;
800 m_dp->addItem(tr("[INFO] Part Start Sector End Sector Size (MB) Type\n"),LOGINFO);
802 for ( i = 0; i < 4; i++ )
804 if (ipod.pinfo[i].start != 0)
806 m_dp->addItem(tr("[INFO] %1 %2 %3 %4 %5 (%6)").arg(
807 i).arg(
808 ipod.pinfo[i].start).arg(
809 ipod.pinfo[i].start+ipod.pinfo[i].size-1).arg(
810 ipod.pinfo[i].size/sectors_per_MB).arg(
811 get_parttype(ipod.pinfo[i].type)).arg(
812 ipod.pinfo[i].type),LOGWARNING);
815 emit done(true);
816 return;
819 read_directory(&ipod);
821 if (ipod.nimages <= 0)
823 m_dp->addItem(tr("Failed to read firmware directory"),LOGERROR);
824 emit done(true);
825 return;
827 if (getmodel(&ipod,(ipod.ipod_directory[0].vers>>8)) < 0)
829 m_dp->addItem(tr("Unknown version number in firmware (%1)").arg(
830 ipod.ipod_directory[0].vers),LOGERROR);
831 emit done(true);
832 return;
835 if (ipod.macpod)
837 m_dp->addItem(tr("Warning this is a MacPod, Rockbox doesnt work on "
838 "this. Convert it to WinPod\n"
839 "See http://www.rockbox.org/wiki/IpodConverstionToFAT32"),
840 LOGWARNING);
841 emit done(true);
842 return;
845 if (ipod_reopen_rw(&ipod) < 0)
847 m_dp->addItem(tr("Could not open Ipod in RW mode"),LOGERROR);
848 emit done(true);
849 return;
852 if (add_bootloader(&ipod, m_tempfilename.toLatin1().data(), FILETYPE_DOT_IPOD)==0)
854 m_dp->addItem(tr("Successfully added Bootloader"),LOGOK);
855 createInstallLog();
856 emit done(false);
857 ipod_close(&ipod);
858 return;
860 else
862 m_dp->addItem(tr("failed to add Bootloader"),LOGERROR);
863 ipod_close(&ipod);
864 emit done(true);
865 return;
869 /**************************************************
870 *** sansa secific code
871 ***************************************************/
872 // reserves memory for sansapatcher
873 bool initSansapatcher()
875 if (sansa_alloc_buffer(&sectorbuf,BUFFER_SIZE) < 0) return true;
876 else return false;
880 void BootloaderInstaller::sansaPrepare()
882 m_dp->addItem(tr("Searching for sansas"),LOGINFO);
883 struct sansa_t sansa;
885 int n = sansa_scan(&sansa);
886 if (n == 0)
888 m_dp->addItem(tr("No Sansa found"),LOGERROR);
889 emit done(true);
890 return;
892 if (n > 1)
894 m_dp->addItem(tr("Too many Sansas found"),LOGERROR);
895 emit done(true);
898 if(m_install) // Installation
900 QString url = m_bootloaderUrlBase + "/sandisk-sansa/"
901 + QString(sansa.targetname) + "/" + m_bootloadername;
903 m_dp->addItem(tr("Downloading file %1.%2")
904 .arg(QFileInfo(url).baseName(), QFileInfo(url).completeSuffix()),LOGINFO);
906 // temporary file needs to be opened to get the filename
907 downloadFile.open();
908 m_tempfilename = downloadFile.fileName();
909 downloadFile.close();
910 // get the real file.
911 getter = new HttpGet(this);
912 getter->setProxy(m_proxy);
913 getter->setFile(&downloadFile);
914 getter->getFile(QUrl(url));
915 // connect signals from HttpGet
916 connect(getter, SIGNAL(done(bool)), this, SLOT(downloadDone(bool)));
917 connect(getter, SIGNAL(dataReadProgress(int, int)), this, SLOT(updateDataReadProgress(int, int)));
918 connect(m_dp, SIGNAL(aborted()), getter, SLOT(abort()));
920 else // Uninstallation
923 if (sansa_open(&sansa, 0) < 0)
925 m_dp->addItem(tr("could not open Sansa"),LOGERROR);
926 emit done(true);
927 return;
930 if (sansa_read_partinfo(&sansa,0) < 0)
932 m_dp->addItem(tr("could not read partitiontable"),LOGERROR);
933 emit done(true);
934 return;
937 int i = is_sansa(&sansa);
938 if (i < 0) {
939 m_dp->addItem(tr("Disk is not a Sansa (%1), aborting.").arg(i),LOGERROR);
940 emit done(true);
941 return;
944 if (sansa.hasoldbootloader)
946 m_dp->addItem(tr("********************************************\n"
947 "OLD ROCKBOX INSTALLATION DETECTED, ABORTING.\n"
948 "You must reinstall the original Sansa firmware before running\n"
949 "sansapatcher for the first time.\n"
950 "See http://www.rockbox.org/twiki/bin/view/Main/SansaE200Install\n"
951 "*********************************************\n"),LOGERROR);
952 emit done(true);
953 return;
957 if (sansa_reopen_rw(&sansa) < 0)
959 m_dp->addItem(tr("Could not open Sansa in RW mode"),LOGERROR);
960 emit done(true);
961 return;
964 if (sansa_delete_bootloader(&sansa)==0)
966 m_dp->addItem(tr("Successfully removed Bootloader"),LOGOK);
967 removeInstallLog();
968 emit done(false);
969 sansa_close(&sansa);
970 return;
972 else
974 m_dp->addItem(tr("--delete-bootloader failed."),LOGERROR);
975 emit done(true);
976 sansa_close(&sansa);
977 return;
982 void BootloaderInstaller::sansaFinish()
984 struct sansa_t sansa;
985 sansa_scan(&sansa);
987 if (sansa_open(&sansa, 0) < 0)
989 m_dp->addItem(tr("could not open Sansa"),LOGERROR);
990 emit done(true);
991 return;
994 if (sansa_read_partinfo(&sansa,0) < 0)
996 m_dp->addItem(tr("could not read partitiontable"),LOGERROR);
997 emit done(true);
998 return;
1002 int i = is_sansa(&sansa);
1003 if (i < 0) {
1005 m_dp->addItem(tr("Disk is not a Sansa (%1), aborting.").arg(i),LOGERROR);
1006 emit done(true);
1007 return;
1010 if (sansa.hasoldbootloader)
1012 m_dp->addItem(tr("********************************************\n"
1013 "OLD ROCKBOX INSTALLATION DETECTED, ABORTING.\n"
1014 "You must reinstall the original Sansa firmware before running\n"
1015 "sansapatcher for the first time.\n"
1016 "See http://www.rockbox.org/twiki/bin/view/Main/SansaE200Install\n"
1017 "*********************************************\n"),LOGERROR);
1018 emit done(true);
1019 return;
1022 if (sansa_reopen_rw(&sansa) < 0)
1024 m_dp->addItem(tr("Could not open Sansa in RW mode"),LOGERROR);
1025 emit done(true);
1026 return;
1029 if (sansa_add_bootloader(&sansa, m_tempfilename.toLatin1().data(), FILETYPE_MI4)==0)
1031 m_dp->addItem(tr("Successfully added Bootloader"),LOGOK);
1032 createInstallLog();
1033 emit done(false);
1034 sansa_close(&sansa);
1035 return;
1037 else
1039 m_dp->addItem(tr("failed to add Bootloader"),LOGERROR);
1040 sansa_close(&sansa);
1041 emit done(true);
1042 return;
1047 /**************************************************
1048 *** iriver /fwpatcher secific code
1049 ***************************************************/
1051 void BootloaderInstaller::iriverPrepare()
1053 char md5sum_str[32];
1054 if (!FileMD5(m_origfirmware, md5sum_str)) {
1055 m_dp->addItem(tr("Could not MD5Sum original firmware"),LOGERROR);
1056 emit done(true);
1057 return;
1060 /* Check firmware against md5sums in h120sums and h100sums */
1061 series = 0;
1062 table_entry = intable(md5sum_str, &h120pairs[0],
1063 sizeof(h120pairs)/sizeof(struct sumpairs));
1064 if (table_entry >= 0) {
1065 series = 120;
1067 else
1069 table_entry = intable(md5sum_str, &h100pairs[0],
1070 sizeof(h100pairs)/sizeof(struct sumpairs));
1071 if (table_entry >= 0)
1073 series = 100;
1075 else
1077 table_entry = intable(md5sum_str, &h300pairs[0],
1078 sizeof(h300pairs)/sizeof(struct sumpairs));
1079 if (table_entry >= 0)
1080 series = 300;
1083 if (series == 0)
1085 m_dp->addItem(tr("Could not detect firmware type"),LOGERROR);
1086 emit done(true);
1087 return;
1090 QString url = m_bootloaderUrlBase + "/iriver/" + m_bootloadername;
1092 m_dp->addItem(tr("Downloading file %1.%2")
1093 .arg(QFileInfo(url).baseName(), QFileInfo(url).completeSuffix()),LOGINFO);
1095 // temporary file needs to be opened to get the filename
1096 downloadFile.open();
1097 m_tempfilename = downloadFile.fileName();
1098 downloadFile.close();
1099 // get the real file.
1100 getter = new HttpGet(this);
1101 getter->setProxy(m_proxy);
1102 getter->setFile(&downloadFile);
1103 getter->getFile(QUrl(url));
1104 // connect signals from HttpGet
1105 connect(getter, SIGNAL(done(bool)), this, SLOT(downloadDone(bool)));
1106 connect(getter, SIGNAL(dataReadProgress(int, int)), this, SLOT(updateDataReadProgress(int, int)));
1107 connect(m_dp, SIGNAL(aborted()), getter, SLOT(abort()));
1110 void BootloaderInstaller::iriverFinish()
1112 // Patch firmware
1113 char md5sum_str[32];
1114 struct sumpairs *sums = 0;
1115 int origin = 0;
1117 /* get pointer to the correct bootloader.bin */
1118 switch(series) {
1119 case 100:
1120 sums = &h100pairs[0];
1121 origin = 0x1f0000;
1122 break;
1123 case 120:
1124 sums = &h120pairs[0];
1125 origin = 0x1f0000;
1126 break;
1127 case 300:
1128 sums = &h300pairs[0];
1129 origin = 0x3f0000;
1130 break;
1133 // temporary files needs to be opened to get the filename
1134 QTemporaryFile firmwareBin, newBin, newHex;
1135 firmwareBin.open();
1136 newBin.open();
1137 newHex.open();
1138 QString firmwareBinName = firmwareBin.fileName();
1139 QString newBinName = newBin.fileName();
1140 QString newHexName = newHex.fileName();
1141 firmwareBin.close();
1142 newBin.close();
1143 newHex.close();
1145 // iriver decode
1146 if (iriver_decode(m_origfirmware, firmwareBinName, FALSE, STRIP_NONE,m_dp) == -1)
1148 m_dp->addItem(tr("Error in descramble"),LOGERROR);
1149 firmwareBin.remove();
1150 newBin.remove();
1151 newHex.remove();
1152 emit done(true);
1153 return;
1155 // mkboot
1156 if (!mkboot(firmwareBinName, newBinName, m_tempfilename, origin,m_dp))
1158 m_dp->addItem(tr("Error in patching"),LOGERROR);
1159 firmwareBin.remove();
1160 newBin.remove();
1161 newHex.remove();
1162 emit done(true);
1163 return;
1165 // iriver_encode
1166 if (iriver_encode(newBinName, newHexName, FALSE,m_dp) == -1)
1168 m_dp->addItem(tr("Error in scramble"),LOGERROR);
1169 firmwareBin.remove();
1170 newBin.remove();
1171 newHex.remove();
1172 emit done(true);
1173 return;
1176 /* now md5sum it */
1177 if (!FileMD5(newHexName, md5sum_str))
1179 m_dp->addItem(tr("Error in checksumming"),LOGERROR);
1180 firmwareBin.remove();
1181 newBin.remove();
1182 newHex.remove();
1183 emit done(true);
1184 return;
1186 if (strncmp(sums[table_entry].patched, md5sum_str, 32) == 0) {
1187 /* delete temp files */
1188 firmwareBin.remove();
1189 newBin.remove();
1192 // Load patched Firmware to player
1193 QString dest;
1194 if(series == 100)
1195 dest = m_mountpoint + "/ihp_100.hex";
1196 else if(series == 120)
1197 dest = m_mountpoint + "/ihp_120.hex";
1198 else if(series == 300)
1199 dest = m_mountpoint + "/H300.hex";
1201 // copy file
1202 QFile destfile(dest);
1203 if(destfile.exists()) destfile.remove();
1204 if(!newHex.copy(dest))
1206 m_dp->addItem(tr("Could not copy: %1 to %2")
1207 .arg(newHexName,dest),LOGERROR);
1208 emit done(true);
1209 return;
1212 downloadFile.remove();
1213 newHex.remove();
1215 createInstallLog();
1217 m_dp->addItem(tr("Bootloader install finished successfully."),LOGOK);
1218 m_dp->addItem(tr("To finish the Bootloader installation, follow the steps below."),LOGINFO);
1219 m_dp->addItem(tr("1. Eject/Unmount your Device."),LOGINFO);
1220 m_dp->addItem(tr("2. Boot into the original Firmware."),LOGINFO);
1221 m_dp->addItem(tr("3. Use the Firmware flash option in the Original Firmware."),LOGINFO);
1222 m_dp->addItem(tr("4. Reboot."),LOGINFO);
1223 m_dp->abort();
1225 emit done(false); // success