diff options
author | Benjamin Dobell <benjamin.dobell+git@glassechidna.com.au> | 2013-03-07 14:00:52 +0100 |
---|---|---|
committer | Benjamin Dobell <benjamin.dobell+git@glassechidna.com.au> | 2013-03-07 14:12:27 +0100 |
commit | ebbc3e7cd2086a9f62a857dffe9ab0bd1f5da768 (patch) | |
tree | 2267ec17efe5435887cb68169a56418acf7a9f05 /heimdall | |
parent | Previous libusbx fix was a red herring of sorts. Inadvertedly it did fix the (diff) | |
download | Heimdall-ebbc3e7cd2086a9f62a857dffe9ab0bd1f5da768.tar Heimdall-ebbc3e7cd2086a9f62a857dffe9ab0bd1f5da768.tar.gz Heimdall-ebbc3e7cd2086a9f62a857dffe9ab0bd1f5da768.tar.bz2 Heimdall-ebbc3e7cd2086a9f62a857dffe9ab0bd1f5da768.tar.lz Heimdall-ebbc3e7cd2086a9f62a857dffe9ab0bd1f5da768.tar.xz Heimdall-ebbc3e7cd2086a9f62a857dffe9ab0bd1f5da768.tar.zst Heimdall-ebbc3e7cd2086a9f62a857dffe9ab0bd1f5da768.zip |
Diffstat (limited to '')
-rw-r--r-- | heimdall-frontend/Source/mainwindow.cpp | 53 | ||||
-rw-r--r-- | heimdall-frontend/Source/mainwindow.h | 4 | ||||
-rw-r--r-- | heimdall-frontend/aboutform.ui | 2 | ||||
-rw-r--r-- | heimdall-frontend/mainwindow.ui | 239 | ||||
-rw-r--r-- | heimdall/heimdall.vcxproj | 8 | ||||
-rw-r--r-- | heimdall/heimdall.vcxproj.filters | 6 | ||||
-rw-r--r-- | heimdall/source/Arguments.cpp | 37 | ||||
-rw-r--r-- | heimdall/source/Arguments.h | 63 | ||||
-rw-r--r-- | heimdall/source/BridgeManager.cpp | 230 | ||||
-rw-r--r-- | heimdall/source/BridgeManager.h | 31 | ||||
-rw-r--r-- | heimdall/source/ClosePcScreenAction.cpp | 45 | ||||
-rw-r--r-- | heimdall/source/DetectAction.cpp | 40 | ||||
-rw-r--r-- | heimdall/source/DownloadPitAction.cpp | 45 | ||||
-rw-r--r-- | heimdall/source/DumpAction.cpp | 158 | ||||
-rw-r--r-- | heimdall/source/DumpAction.h | 34 | ||||
-rw-r--r-- | heimdall/source/FlashAction.cpp | 451 | ||||
-rw-r--r-- | heimdall/source/Interface.cpp | 4 | ||||
-rw-r--r-- | heimdall/source/Interface.h | 7 | ||||
-rw-r--r-- | heimdall/source/PrintPitAction.cpp | 46 | ||||
-rw-r--r-- | heimdall/source/SendFilePartPacket.h | 5 |
20 files changed, 731 insertions, 777 deletions
diff --git a/heimdall-frontend/Source/mainwindow.cpp b/heimdall-frontend/Source/mainwindow.cpp index f990cdd..281fd77 100644 --- a/heimdall-frontend/Source/mainwindow.cpp +++ b/heimdall-frontend/Source/mainwindow.cpp @@ -262,7 +262,10 @@ void MainWindow::UpdateFlashInterfaceAvailability(void) flashProgressBar->setEnabled(false);
optionsGroup->setEnabled(true);
+ sessionGroup->setEnabled(true);
startFlashButton->setEnabled(validFlashSettings);
+ noRebootCheckBox->setEnabled(validFlashSettings);
+ resumeCheckbox->setEnabled(validFlashSettings);
}
else
{
@@ -270,7 +273,7 @@ void MainWindow::UpdateFlashInterfaceAvailability(void) flashProgressBar->setEnabled(true);
optionsGroup->setEnabled(false);
- startFlashButton->setEnabled(false);
+ sessionGroup->setEnabled(false);
}
}
@@ -314,10 +317,7 @@ void MainWindow::UpdateUtilitiesInterfaceAvailability(void) closePcScreenButton->setEnabled(true);
pitSaveAsButton->setEnabled(true);
- if (!pitDestinationLineEdit->text().isEmpty())
- downloadPitButton->setEnabled(true);
- else
- downloadPitButton->setEnabled(false);
+ downloadPitButton->setEnabled(!pitDestinationLineEdit->text().isEmpty());
if (printPitDeviceRadioBox->isChecked())
{
@@ -331,6 +331,7 @@ void MainWindow::UpdateUtilitiesInterfaceAvailability(void) printLocalPitGroup->setEnabled(true);
printLocalPitLineEdit->setEnabled(true);
printLocalPitBrowseButton->setEnabled(true);
+
printPitButton->setEnabled(!printLocalPitLineEdit->text().isEmpty());
}
}
@@ -420,6 +421,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) // Menu
QObject::connect(actionDonate, SIGNAL(triggered()), this, SLOT(OpenDonationWebpage()));
QObject::connect(actionVerboseOutput, SIGNAL(toggled(bool)), this, SLOT(SetVerboseOutput(bool)));
+ QObject::connect(actionResumeConnection, SIGNAL(toggled(bool)), this, SLOT(SetResume(bool)));
QObject::connect(actionAboutHeimdall, SIGNAL(triggered()), this, SLOT(ShowAbout()));
// Load Package Tab
@@ -439,7 +441,9 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) QObject::connect(pitBrowseButton, SIGNAL(clicked()), this, SLOT(SelectPit()));
QObject::connect(repartitionCheckBox, SIGNAL(stateChanged(int)), this, SLOT(SetRepartition(int)));
+
QObject::connect(noRebootCheckBox, SIGNAL(stateChanged(int)), this, SLOT(SetNoReboot(int)));
+ QObject::connect(resumeCheckbox, SIGNAL(stateChanged(int)), this, SLOT(SetResume(int)));
QObject::connect(startFlashButton, SIGNAL(clicked()), this, SLOT(StartFlash()));
@@ -882,13 +886,32 @@ void MainWindow::SelectPit(void) }
}
+
void MainWindow::SetRepartition(int enabled)
{
workingPackageData.GetFirmwareInfo().SetRepartition(enabled);
+
+ repartitionCheckBox->setChecked(enabled);
}
+
void MainWindow::SetNoReboot(int enabled)
{
workingPackageData.GetFirmwareInfo().SetNoReboot(enabled);
+
+ noRebootCheckBox->setChecked(enabled);
+}
+
+void MainWindow::SetResume(bool enabled)
+{
+ resume = enabled;
+
+ actionResumeConnection->setChecked(enabled);
+ resumeCheckbox->setChecked(enabled);
+}
+
+void MainWindow::SetResume(int enabled)
+{
+ SetResume(enabled != 0);
}
void MainWindow::StartFlash(void)
@@ -922,6 +945,9 @@ void MainWindow::StartFlash(void) if (firmwareInfo.GetNoReboot())
arguments.append("--no-reboot");
+ if (resume)
+ arguments.append("--resume");
+
if (verboseOutput)
arguments.append("--verbose");
@@ -1095,6 +1121,9 @@ void MainWindow::ClosePcScreen(void) QStringList arguments;
arguments.append("close-pc-screen");
+
+ if (resume)
+ arguments.append("--resume");
if (verboseOutput)
arguments.append("--verbose");
@@ -1135,6 +1164,9 @@ void MainWindow::DownloadPit(void) arguments.append("--no-reboot");
+ if (resume)
+ arguments.append("--resume");
+
if (verboseOutput)
arguments.append("--verbose");
@@ -1196,6 +1228,9 @@ void MainWindow::PrintPit(void) arguments.append("--stdout-errors");
arguments.append("--no-reboot");
+
+ if (resume)
+ arguments.append("--resume");
if (verboseOutput)
arguments.append("--verbose");
@@ -1237,6 +1272,8 @@ void MainWindow::HandleHeimdallStdout(void) void MainWindow::HandleHeimdallReturned(int exitCode, QProcess::ExitStatus exitStatus)
{
+ HandleHeimdallStdout();
+
if (exitStatus == QProcess::NormalExit && exitCode == 0)
{
if (heimdallState == MainWindow::kHeimdallStateFlashing)
@@ -1247,6 +1284,12 @@ void MainWindow::HandleHeimdallReturned(int exitCode, QProcess::ExitStatus exitS {
deviceDetectedRadioButton->setChecked(true);
}
+
+ bool executedNoReboot = (heimdallState == kHeimdallStateFlashing && loadedPackageData.GetFirmwareInfo().GetNoReboot())
+ || (heimdallState == kHeimdallStatePrintingPit && printPitDeviceRadioBox->isChecked()) || heimdallState == kHeimdallStateDownloadingPit;
+
+ if (executedNoReboot)
+ SetResume(true);
}
else
{
diff --git a/heimdall-frontend/Source/mainwindow.h b/heimdall-frontend/Source/mainwindow.h index bea15cd..4abee8c 100644 --- a/heimdall-frontend/Source/mainwindow.h +++ b/heimdall-frontend/Source/mainwindow.h @@ -81,6 +81,7 @@ namespace HeimdallFrontend QList<unsigned int> unusedPartitionIds;
bool verboseOutput;
+ bool resume;
void StartHeimdall(const QStringList& arguments);
@@ -133,7 +134,10 @@ namespace HeimdallFrontend void SelectPit(void);
void SetRepartition(int enabled);
+
void SetNoReboot(int enabled);
+ void SetResume(bool enabled);
+ void SetResume(int enabled);
void StartFlash(void);
diff --git a/heimdall-frontend/aboutform.ui b/heimdall-frontend/aboutform.ui index 142de47..ef1b947 100644 --- a/heimdall-frontend/aboutform.ui +++ b/heimdall-frontend/aboutform.ui @@ -114,7 +114,7 @@ p, li { white-space: pre-wrap; }
</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:10pt; font-weight:400; font-style:normal;">
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Heimdall Frontend</span></p>
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Version 1.4 RC1</p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Version 1.4 RC3</p>
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Copyright © 2010-2012 Benjamin Dobell, Glass Echidna</p>
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Heimdall (command line)</span></p>
diff --git a/heimdall-frontend/mainwindow.ui b/heimdall-frontend/mainwindow.ui index 6a165fb..ce42a89 100644 --- a/heimdall-frontend/mainwindow.ui +++ b/heimdall-frontend/mainwindow.ui @@ -401,7 +401,7 @@ <rect>
<x>10</x>
<y>300</y>
- <width>751</width>
+ <width>511</width>
<height>171</height>
</rect>
</property>
@@ -414,9 +414,9 @@ </property>
<property name="geometry">
<rect>
- <x>350</x>
+ <x>280</x>
<y>130</y>
- <width>271</width>
+ <width>221</width>
<height>31</height>
</rect>
</property>
@@ -432,8 +432,8 @@ <rect>
<x>10</x>
<y>30</y>
- <width>731</width>
- <height>91</height>
+ <width>491</width>
+ <height>81</height>
</rect>
</property>
<property name="undoRedoEnabled">
@@ -451,7 +451,7 @@ <rect>
<x>10</x>
<y>130</y>
- <width>331</width>
+ <width>261</width>
<height>21</height>
</rect>
</property>
@@ -468,59 +468,6 @@ <set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
</property>
</widget>
- <widget class="QPushButton" name="startFlashButton">
- <property name="enabled">
- <bool>false</bool>
- </property>
- <property name="geometry">
- <rect>
- <x>620</x>
- <y>130</y>
- <width>91</width>
- <height>31</height>
- </rect>
- </property>
- <property name="text">
- <string>Start</string>
- </property>
- </widget>
- <widget class="QLabel" name="startFlashTipLabel">
- <property name="geometry">
- <rect>
- <x>720</x>
- <y>130</y>
- <width>21</width>
- <height>23</height>
- </rect>
- </property>
- <property name="font">
- <font>
- <weight>75</weight>
- <bold>true</bold>
- </font>
- </property>
- <property name="toolTip">
- <string notr="true">The "Start" button will remain inactive until at least one partition/file is added.</string>
- </property>
- <property name="frameShape">
- <enum>QFrame::Panel</enum>
- </property>
- <property name="frameShadow">
- <enum>QFrame::Raised</enum>
- </property>
- <property name="lineWidth">
- <number>2</number>
- </property>
- <property name="midLineWidth">
- <number>0</number>
- </property>
- <property name="text">
- <string>?</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignCenter</set>
- </property>
- </widget>
</widget>
<widget class="QGroupBox" name="optionsGroup">
<property name="geometry">
@@ -540,7 +487,7 @@ <x>10</x>
<y>20</y>
<width>391</width>
- <height>61</height>
+ <height>91</height>
</rect>
</property>
<property name="title">
@@ -624,6 +571,25 @@ <set>Qt::AlignCenter</set>
</property>
</widget>
+ <widget class="QCheckBox" name="repartitionCheckBox">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>60</y>
+ <width>131</width>
+ <height>21</height>
+ </rect>
+ </property>
+ <property name="toolTip">
+ <string notr="true">Repartitioning will wipe all data for your phone and install the selected PIT file.</string>
+ </property>
+ <property name="text">
+ <string>Repartition</string>
+ </property>
+ </widget>
</widget>
<widget class="QGroupBox" name="partitionGroup">
<property name="geometry">
@@ -738,44 +704,6 @@ </property>
</widget>
</widget>
- <widget class="QCheckBox" name="noRebootCheckBox">
- <property name="enabled">
- <bool>false</bool>
- </property>
- <property name="geometry">
- <rect>
- <x>250</x>
- <y>90</y>
- <width>151</width>
- <height>21</height>
- </rect>
- </property>
- <property name="toolTip">
- <string notr="true">Can be enabled to prevent your device rebooting after the flash finishes.</string>
- </property>
- <property name="text">
- <string>No Reboot</string>
- </property>
- </widget>
- <widget class="QCheckBox" name="repartitionCheckBox">
- <property name="enabled">
- <bool>false</bool>
- </property>
- <property name="geometry">
- <rect>
- <x>20</x>
- <y>90</y>
- <width>151</width>
- <height>21</height>
- </rect>
- </property>
- <property name="toolTip">
- <string notr="true">Repartitioning will wipe all data for your phone and install the selected PIT file.</string>
- </property>
- <property name="text">
- <string>Repartition</string>
- </property>
- </widget>
<widget class="QGroupBox" name="partitionsGroup">
<property name="geometry">
<rect>
@@ -872,6 +800,110 @@ </widget>
</widget>
</widget>
+ <widget class="QGroupBox" name="sessionGroup">
+ <property name="geometry">
+ <rect>
+ <x>530</x>
+ <y>300</y>
+ <width>231</width>
+ <height>171</height>
+ </rect>
+ </property>
+ <property name="title">
+ <string>Session</string>
+ </property>
+ <widget class="QCheckBox" name="noRebootCheckBox">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>30</y>
+ <width>211</width>
+ <height>21</height>
+ </rect>
+ </property>
+ <property name="toolTip">
+ <string notr="true">Can be enabled to prevent your device rebooting after the flash finishes.</string>
+ </property>
+ <property name="text">
+ <string>No Reboot</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" name="resumeCheckbox">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>60</y>
+ <width>211</width>
+ <height>21</height>
+ </rect>
+ </property>
+ <property name="toolTip">
+ <string notr="true">Can be enabled to prevent your device rebooting after the flash finishes.</string>
+ </property>
+ <property name="text">
+ <string>Resume (use after "No Reboot")</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" name="startFlashButton">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>50</x>
+ <y>120</y>
+ <width>111</width>
+ <height>31</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>Start</string>
+ </property>
+ </widget>
+ <widget class="QLabel" name="startFlashTipLabel">
+ <property name="geometry">
+ <rect>
+ <x>170</x>
+ <y>120</y>
+ <width>21</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <property name="font">
+ <font>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
+ <property name="toolTip">
+ <string notr="true">The "Start" button will remain inactive until at least one partition/file is added.</string>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::Panel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Raised</enum>
+ </property>
+ <property name="lineWidth">
+ <number>2</number>
+ </property>
+ <property name="midLineWidth">
+ <number>0</number>
+ </property>
+ <property name="text">
+ <string>?</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </widget>
</widget>
<widget class="QWidget" name="createPackageTab">
<property name="enabled">
@@ -1826,6 +1858,8 @@ <property name="title">
<string>Advanced</string>
</property>
+ <addaction name="actionResumeConnection"/>
+ <addaction name="separator"/>
<addaction name="actionVerboseOutput"/>
</widget>
<addaction name="menuDonate"/>
@@ -1860,6 +1894,14 @@ <string>Verbose Output</string>
</property>
</action>
+ <action name="actionResumeConnection">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Resume Connection</string>
+ </property>
+ </action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<tabstops>
@@ -1883,7 +1925,6 @@ <tabstop>partitionFileLineEdit</tabstop>
<tabstop>partitionFileBrowseButton</tabstop>
<tabstop>outputPlainTextEdit</tabstop>
- <tabstop>startFlashButton</tabstop>
<tabstop>createFirmwareNameLineEdit</tabstop>
<tabstop>createFirmwareVersionLineEdit</tabstop>
<tabstop>createPlatformNameLineEdit</tabstop>
diff --git a/heimdall/heimdall.vcxproj b/heimdall/heimdall.vcxproj index 790b909..558dcd7 100644 --- a/heimdall/heimdall.vcxproj +++ b/heimdall/heimdall.vcxproj @@ -68,10 +68,10 @@ <SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>libusb-1.0.lib;libpit.lib;%(AdditionalDependencies)</AdditionalDependencies>
- <AdditionalLibraryDirectories>$(SolutionDir)libusbx-1.0\lib\$(Platform)\Release\;$(SolutionDir)$(Platform)\$(Configuration)\lib\</AdditionalLibraryDirectories>
+ <AdditionalLibraryDirectories>$(SolutionDir)libusbx-1.0\lib\$(Platform)\$(Configuration)\;$(SolutionDir)$(Platform)\$(Configuration)\lib\</AdditionalLibraryDirectories>
</Link>
<PostBuildEvent>
- <Command>xcopy /y $(SolutionDir)libusbx-1.0\lib\$(Platform)\Release\libusb-1.0.dll $(SolutionDir)$(Platform)\$(Configuration)\</Command>
+ <Command>xcopy /y $(SolutionDir)libusbx-1.0\lib\$(Platform)\$(Configuration)\libusb-1.0.dll $(SolutionDir)$(Platform)\$(Configuration)\</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@@ -95,7 +95,7 @@ <EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>libusb-1.0.lib;libpit.lib;%(AdditionalDependencies)</AdditionalDependencies>
- <AdditionalLibraryDirectories>$(SolutionDir)libusbx-1.0\lib\$(Platform)\Release\;$(SolutionDir)$(Platform)\$(Configuration)\lib\</AdditionalLibraryDirectories>
+ <AdditionalLibraryDirectories>$(SolutionDir)libusbx-1.0\lib\$(Platform)\$(Configuration)\;$(SolutionDir)$(Platform)\$(Configuration)\lib\</AdditionalLibraryDirectories>
</Link>
<PostBuildEvent>
<Command>xcopy /y $(SolutionDir)libusbx-1.0\lib\$(Platform)\$(Configuration)\libusb-1.0.dll $(SolutionDir)$(Platform)\$(Configuration)\</Command>
@@ -109,7 +109,6 @@ <ClInclude Include="source\ClosePcScreenAction.h" />
<ClInclude Include="source\DetectAction.h" />
<ClInclude Include="source\DownloadPitAction.h" />
- <ClInclude Include="source\DumpAction.h" />
<ClInclude Include="source\FlashAction.h" />
<ClInclude Include="source\HelpAction.h" />
<ClInclude Include="source\InfoAction.h" />
@@ -151,7 +150,6 @@ <ClCompile Include="source\ClosePcScreenAction.cpp" />
<ClCompile Include="source\DetectAction.cpp" />
<ClCompile Include="source\DownloadPitAction.cpp" />
- <ClCompile Include="source\DumpAction.cpp" />
<ClCompile Include="source\FlashAction.cpp" />
<ClCompile Include="source\HelpAction.cpp" />
<ClCompile Include="source\InfoAction.cpp" />
diff --git a/heimdall/heimdall.vcxproj.filters b/heimdall/heimdall.vcxproj.filters index 6cec0df..cbc0f98 100644 --- a/heimdall/heimdall.vcxproj.filters +++ b/heimdall/heimdall.vcxproj.filters @@ -130,9 +130,6 @@ <ClInclude Include="source\Utility.h">
<Filter>Source</Filter>
</ClInclude>
- <ClInclude Include="source\DumpAction.h">
- <Filter>Source\Interface</Filter>
- </ClInclude>
<ClInclude Include="source\DetectAction.h">
<Filter>Source\Interface</Filter>
</ClInclude>
@@ -174,9 +171,6 @@ <ClCompile Include="source\Utility.cpp">
<Filter>Source</Filter>
</ClCompile>
- <ClCompile Include="source\DumpAction.cpp">
- <Filter>Source\Interface</Filter>
- </ClCompile>
<ClCompile Include="source\DetectAction.cpp">
<Filter>Source\Interface</Filter>
</ClCompile>
diff --git a/heimdall/source/Arguments.cpp b/heimdall/source/Arguments.cpp index 1c3a17e..7f2d9ee 100644 --- a/heimdall/source/Arguments.cpp +++ b/heimdall/source/Arguments.cpp @@ -24,20 +24,21 @@ #include "Interface.h" #include "Utility.h" +using namespace std; using namespace Heimdall; -FlagArgument *FlagArgument::ParseArgument(int argc, char **argv, int& argi) +FlagArgument *FlagArgument::ParseArgument(const std::string& name, int argc, char **argv, int& argi) { - return new FlagArgument(); + return new FlagArgument(name); } -StringArgument *StringArgument::ParseArgument(int argc, char **argv, int& argi) +StringArgument *StringArgument::ParseArgument(const std::string& name, int argc, char **argv, int& argi) { if (++argi < argc) { - return (new StringArgument(argv[argi])); + return (new StringArgument(name, argv[argi])); } else { @@ -48,7 +49,7 @@ StringArgument *StringArgument::ParseArgument(int argc, char **argv, int& argi) -UnsignedIntegerArgument *UnsignedIntegerArgument::ParseArgument(int argc, char **argv, int& argi) +UnsignedIntegerArgument *UnsignedIntegerArgument::ParseArgument(const std::string& name, int argc, char **argv, int& argi) { UnsignedIntegerArgument *unsignedIntegerArgument = nullptr; @@ -57,7 +58,7 @@ UnsignedIntegerArgument *UnsignedIntegerArgument::ParseArgument(int argc, char * unsigned int value; if (Utility::ParseUnsignedInt(value, argv[argi]) == kNumberParsingStatusSuccess) - unsignedIntegerArgument = new UnsignedIntegerArgument(value); + unsignedIntegerArgument = new UnsignedIntegerArgument(name, value); else Interface::Print("%s must be a positive integer.", argv[argi - 1]); } @@ -81,8 +82,8 @@ Arguments::Arguments(const map<string, ArgumentType>& argumentTypes, const map<s Arguments::~Arguments() { - for (map<string, Argument *>::const_iterator it = arguments.begin(); it != arguments.end(); it++) - delete it->second; + for (vector<const Argument *>::const_iterator it = argumentVector.begin(); it != argumentVector.end(); it++) + delete *it; } bool Arguments::ParseArguments(int argc, char **argv, int argi) @@ -158,6 +159,10 @@ bool Arguments::ParseArguments(int argc, char **argv, int argi) } } + // We don't want to insert wild-cards into our argument map. + if (argumentName == "%d" || argumentName == "%s") + argumentName = nonwildcardArgumentName; + Argument *argument = nullptr; if (argumentTypeIt != argumentTypes.end()) @@ -165,15 +170,15 @@ bool Arguments::ParseArguments(int argc, char **argv, int argi) switch (argumentTypeIt->second) { case kArgumentTypeFlag: - argument = FlagArgument::ParseArgument(argc, argv, argi); + argument = FlagArgument::ParseArgument(argumentName, argc, argv, argi); break; case kArgumentTypeString: - argument = StringArgument::ParseArgument(argc, argv, argi); + argument = StringArgument::ParseArgument(argumentName, argc, argv, argi); break; case kArgumentTypeUnsignedInteger: - argument = UnsignedIntegerArgument::ParseArgument(argc, argv, argi); + argument = UnsignedIntegerArgument::ParseArgument(argumentName, argc, argv, argi); break; default: @@ -186,21 +191,19 @@ bool Arguments::ParseArguments(int argc, char **argv, int argi) Interface::Print("Unknown argument: %s\n\n", argv[argi]); } - // We don't want to insert wild-cards into our argument map. - if (argumentName == "%d" || argumentName == "%s") - argumentName = nonwildcardArgumentName; - if (argument) { - pair<map<string, Argument *>::iterator, bool> insertResult = arguments.insert(pair<string, Argument *>(argumentName, argument)); + pair<map<string, const Argument *>::iterator, bool> insertResult = argumentMap.insert(pair<string, const Argument *>(argumentName, argument)); if (!insertResult.second) { - Interface::Print("Duplicate argument: %s (%s)\n\n", argv[argi], insertResult.first->first.c_str()); + Interface::Print("Duplicate argument: %s (%s)\n\n", argv[argi], argumentName); delete argument; return (false); } + + argumentVector.push_back(argument); } else { diff --git a/heimdall/source/Arguments.h b/heimdall/source/Arguments.h index 17f31fa..b64028b 100644 --- a/heimdall/source/Arguments.h +++ b/heimdall/source/Arguments.h @@ -24,12 +24,11 @@ // C/C++ Standard Library #include <map> #include <string> +#include <vector> // Heimdall #include "Heimdall.h" -using namespace std; - namespace Heimdall { typedef enum @@ -37,20 +36,21 @@ namespace Heimdall kArgumentTypeFlag = 0, kArgumentTypeString, kArgumentTypeUnsignedInteger - } ArgumentType; class Argument { private: - ArgumentType argumentType; + std::string name; + ArgumentType type; protected: - Argument(ArgumentType argumentType) + Argument(const std::string& name, ArgumentType type) { - this->argumentType = argumentType; + this->name = name; + this->type = type; } public: @@ -59,9 +59,14 @@ namespace Heimdall { } - ArgumentType GetArgumentType(void) const + const std::string& GetName(void) const + { + return name; + } + + ArgumentType GetType(void) const { - return argumentType; + return type; } }; @@ -69,31 +74,31 @@ namespace Heimdall { private: - FlagArgument() : Argument(kArgumentTypeFlag) + FlagArgument(const std::string& name) : Argument(name, kArgumentTypeFlag) { } public: - static FlagArgument *ParseArgument(int argc, char **argv, int& argi); + static FlagArgument *ParseArgument(const std::string& name, int argc, char **argv, int& argi); }; class StringArgument : public Argument { private: - string value; + std::string value; - StringArgument(const string& value) : Argument(kArgumentTypeString) + StringArgument(const std::string& name, const std::string& value) : Argument(name, kArgumentTypeString) { this->value = value; } public: - static StringArgument *ParseArgument(int argc, char **argv, int& argi); + static StringArgument *ParseArgument(const std::string& name, int argc, char **argv, int& argi); - const string& GetValue(void) const + const std::string& GetValue(void) const { return (value); } @@ -105,14 +110,14 @@ namespace Heimdall unsigned int value; - UnsignedIntegerArgument(unsigned int value) : Argument(kArgumentTypeUnsignedInteger) + UnsignedIntegerArgument(const std::string& name, unsigned int value) : Argument(name, kArgumentTypeUnsignedInteger) { this->value = value; } public: - static UnsignedIntegerArgument *ParseArgument(int argc, char **argv, int& argi); + static UnsignedIntegerArgument *ParseArgument(const std::string& name, int argc, char **argv, int& argi); unsigned int GetValue(void) const { @@ -124,36 +129,38 @@ namespace Heimdall { private: - const map<string, ArgumentType> argumentTypes; - const map<string, string> shortArgumentAliases; - const map<string, string> argumentAliases; + const std::map<std::string, ArgumentType> argumentTypes; + const std::map<std::string, std::string> shortArgumentAliases; + const std::map<std::string, std::string> argumentAliases; - map<string, Argument *> arguments; + std::vector<const Argument *> argumentVector; + std::map<std::string, const Argument *> argumentMap; public: - Arguments(const map<string, ArgumentType>& argumentTypes, const map<string, string>& shortArgumentAliases = (map<string, string>()), - const map<string, string>& argumentAliases = (map<string, string>())); + Arguments(const std::map<std::string, ArgumentType>& argumentTypes, + const std::map<std::string, std::string>& shortArgumentAliases = std::map<std::string, std::string>(), + const std::map<std::string, std::string>& argumentAliases = std::map<std::string, std::string>()); ~Arguments(); // argi is the index of the first argument to parse. bool ParseArguments(int argc, char **argv, int argi); - const Argument *GetArgument(string argumentName) const + const Argument *GetArgument(std::string argumentName) const { - map<string, Argument *>::const_iterator it = arguments.find(argumentName); - return (it != arguments.end() ? it->second : nullptr); + std::map<std::string, const Argument *>::const_iterator it = argumentMap.find(argumentName); + return (it != argumentMap.end() ? it->second : nullptr); } - const map<string, ArgumentType>& GetArgumentTypes(void) const + const std::map<std::string, ArgumentType>& GetArgumentTypes(void) const { return (argumentTypes); } - const map<string, Argument *>& GetArguments(void) const + const std::vector<const Argument *>& GetArguments(void) const { - return (arguments); + return (argumentVector); } }; } diff --git a/heimdall/source/BridgeManager.cpp b/heimdall/source/BridgeManager.cpp index aa7b969..8f1b32e 100644 --- a/heimdall/source/BridgeManager.cpp +++ b/heimdall/source/BridgeManager.cpp @@ -57,6 +57,7 @@ #define USB_CLASS_CDC_DATA 0x0A +using namespace libpit; using namespace Heimdall; const DeviceIdentifier BridgeManager::supportedDevices[BridgeManager::kSupportedDeviceCount] = { @@ -68,7 +69,7 @@ const DeviceIdentifier BridgeManager::supportedDevices[BridgeManager::kSupported enum { - kDumpBufferSize = 4096 + kDumpBufferSize = 4096, }; enum @@ -84,6 +85,11 @@ enum kReceivePacketMaxAttempts = 5 }; +enum +{ + kPitSizeMultiplicand = 4096 +}; + int BridgeManager::FindDeviceInterface(void) { Interface::Print("Detecting device...\n"); @@ -302,34 +308,7 @@ void BridgeManager::ReleaseDeviceInterface(void) Interface::Print("\n"); } -bool BridgeManager::CheckProtocol(void) const -{ - Interface::Print("Checking if protocol is initialised...\n"); - - DeviceTypePacket deviceTypePacket; - - if (!SendPacket(&deviceTypePacket, 150, false)) - { - Interface::Print("Protocol is not initialised.\n"); - return (false); - } - - unsigned char buffer[1024]; - memset(buffer, 0, sizeof(buffer)); - - SessionSetupResponse deviceTypeResponse; - - if (!ReceivePacket(&deviceTypeResponse, 150, false, buffer, sizeof(buffer))) - { - Interface::Print("Protocol is not initialised.\n\n"); - return (false); - } - - Interface::Print("Protocol is initialised.\n\n"); - return (true); -} - -bool BridgeManager::InitialiseProtocol(void) const +bool BridgeManager::InitialiseProtocol(void) { Interface::Print("Initialising protocol...\n"); @@ -488,6 +467,8 @@ BridgeManager::BridgeManager(bool verbose, int communicationDelay) fileTransferSequenceMaxLength = kFileTransferSequenceMaxLengthDefault; fileTransferPacketSize = kFileTransferPacketSizeDefault; fileTransferSequenceTimeout = kFileTransferSequenceTimeoutDefault; + + usbLogLevel = UsbLogLevel::Default; } BridgeManager::~BridgeManager() @@ -507,14 +488,39 @@ BridgeManager::~BridgeManager() bool BridgeManager::DetectDevice(void) { - // Initialise libusb-1.0 + // Initialise libusb int result = libusb_init(&libusbContext); + if (result != LIBUSB_SUCCESS) { Interface::PrintError("Failed to initialise libusb. libusb error: %d\n", result); return (false); } + // Setup libusb log level. + switch (usbLogLevel) + { + case UsbLogLevel::None: + libusb_set_debug(libusbContext, LIBUSB_LOG_LEVEL_NONE); + break; + + case UsbLogLevel::Error: + libusb_set_debug(libusbContext, LIBUSB_LOG_LEVEL_ERROR); + break; + + case UsbLogLevel::Warning: + libusb_set_debug(libusbContext, LIBUSB_LOG_LEVEL_WARNING); + break; + + case UsbLogLevel::Info: + libusb_set_debug(libusbContext, LIBUSB_LOG_LEVEL_INFO); + break; + + case UsbLogLevel::Debug: + libusb_set_debug(libusbContext, LIBUSB_LOG_LEVEL_DEBUG); + break; + } + // Get handle to Galaxy S device struct libusb_device **devices; int deviceCount = libusb_get_device_list(libusbContext, &devices); @@ -542,11 +548,11 @@ bool BridgeManager::DetectDevice(void) return (false); } -int BridgeManager::Initialise() +int BridgeManager::Initialise(bool resume) { Interface::Print("Initialising connection...\n"); - // Initialise libusb-1.0 + // Initialise libusb int result = libusb_init(&libusbContext); if (result != LIBUSB_SUCCESS) @@ -555,6 +561,30 @@ int BridgeManager::Initialise() Interface::Print("Failed to connect to device!"); return (BridgeManager::kInitialiseFailed); } + + // Setup libusb log level. + switch (usbLogLevel) + { + case UsbLogLevel::None: + libusb_set_debug(libusbContext, LIBUSB_LOG_LEVEL_NONE); + break; + + case UsbLogLevel::Error: + libusb_set_debug(libusbContext, LIBUSB_LOG_LEVEL_ERROR); + break; + + case UsbLogLevel::Warning: + libusb_set_debug(libusbContext, LIBUSB_LOG_LEVEL_WARNING); + break; + + case UsbLogLevel::Info: + libusb_set_debug(libusbContext, LIBUSB_LOG_LEVEL_INFO); + break; + + case UsbLogLevel::Debug: + libusb_set_debug(libusbContext, LIBUSB_LOG_LEVEL_DEBUG); + break; + } result = FindDeviceInterface(); @@ -567,7 +597,7 @@ int BridgeManager::Initialise() if (!SetupDeviceInterface()) return (BridgeManager::kInitialiseFailed); - if (!CheckProtocol()) + if (!resume) { if (!InitialiseProtocol()) return (BridgeManager::kInitialiseFailed); @@ -865,11 +895,9 @@ bool BridgeManager::RequestDeviceType(unsigned int request, int *result) const return (true); } -bool BridgeManager::SendPitFile(FILE *file) const +bool BridgeManager::SendPitData(const PitData *pitData) const { - fseek(file, 0, SEEK_END); - long fileSize = ftell(file); - rewind(file); + unsigned int pitBufferSize = pitData->GetPaddedSize(); // Start file transfer PitFilePacket *pitFilePacket = new PitFilePacket(PitFilePacket::kRequestFlash); @@ -893,7 +921,7 @@ bool BridgeManager::SendPitFile(FILE *file) const } // Transfer file size - FlashPartPitFilePacket *flashPartPitFilePacket = new FlashPartPitFilePacket(fileSize); + FlashPartPitFilePacket *flashPartPitFilePacket = new FlashPartPitFilePacket(pitBufferSize); success = SendPacket(flashPartPitFilePacket); delete flashPartPitFilePacket; @@ -913,11 +941,20 @@ bool BridgeManager::SendPitFile(FILE *file) const return (false); } + // Create packed in-memory PIT file + + unsigned char *pitBuffer = new unsigned char[pitBufferSize]; + memset(pitBuffer, 0, pitBufferSize); + + pitData->Pack(pitBuffer); + // Flash pit file - SendFilePartPacket *sendFilePartPacket = new SendFilePartPacket(file, fileSize); + SendFilePartPacket *sendFilePartPacket = new SendFilePartPacket(pitBuffer, pitBufferSize); success = SendPacket(sendFilePartPacket); delete sendFilePartPacket; + delete [] pitBuffer; + if (!success) { Interface::PrintError("Failed to send file part packet!\n"); @@ -935,7 +972,7 @@ bool BridgeManager::SendPitFile(FILE *file) const } // End pit file transfer - EndPitFileTransferPacket *endPitFileTransferPacket = new EndPitFileTransferPacket(fileSize); + EndPitFileTransferPacket *endPitFileTransferPacket = new EndPitFileTransferPacket(pitBufferSize); success = SendPacket(endPitFileTransferPacket); delete endPitFileTransferPacket; @@ -1320,106 +1357,33 @@ bool BridgeManager::SendFile(FILE *file, unsigned int destination, unsigned int return (true); } -bool BridgeManager::ReceiveDump(unsigned int chipType, unsigned int chipId, FILE *file) const +void BridgeManager::SetUsbLogLevel(UsbLogLevel usbLogLevel) { - bool success; - - // Start file transfer - BeginDumpPacket *beginDumpPacket = new BeginDumpPacket(chipType, chipId); - success = SendPacket(beginDumpPacket); - delete beginDumpPacket; + this->usbLogLevel = usbLogLevel; - if (!success) - { - Interface::PrintError("Failed to request dump!\n"); - return (false); - } - - DumpResponse *dumpResponse = new DumpResponse(); - success = ReceivePacket(dumpResponse); - unsigned int dumpSize = dumpResponse->GetDumpSize(); - delete dumpResponse; - - if (!success) - { - Interface::PrintError("Failed to receive dump size!\n"); - return (false); - } - - unsigned int transferCount = dumpSize / ReceiveFilePartPacket::kDataSize; - if (transferCount % ReceiveFilePartPacket::kDataSize != 0) - transferCount++; - - char *buffer = new char[kDumpBufferSize * ReceiveFilePartPacket::kDataSize]; - unsigned int bufferOffset = 0; - - for (unsigned int i = 0; i < transferCount; i++) + if (libusbContext) { - DumpPartFileTransferPacket *dumpPartPacket = new DumpPartFileTransferPacket(i); - success = SendPacket(dumpPartPacket); - delete dumpPartPacket; - - if (!success) - { - Interface::PrintError("Failed to request dump part #%d!\n", i); - delete [] buffer; - return (false); - } - - ReceiveFilePartPacket *receiveFilePartPacket = new ReceiveFilePartPacket(); - success = ReceivePacket(receiveFilePartPacket); - - if (!success) - { - Interface::PrintError("Failed to receive dump part #%d!\n", i); - continue; - delete receiveFilePartPacket; - delete [] buffer; - return (true); - } - - if (bufferOffset + receiveFilePartPacket->GetReceivedSize() > kDumpBufferSize * ReceiveFilePartPacket::kDataSize) + switch (usbLogLevel) { - // Write the buffer to the output file - fwrite(buffer, 1, bufferOffset, file); - bufferOffset = 0; - } - - // Copy the packet data into pitFile. - memcpy(buffer + bufferOffset, receiveFilePartPacket->GetData(), receiveFilePartPacket->GetReceivedSize()); - bufferOffset += receiveFilePartPacket->GetReceivedSize(); - - delete receiveFilePartPacket; - } - - if (bufferOffset != 0) - { - // Write the buffer to the output file - fwrite(buffer, 1, bufferOffset, file); - } - - delete [] buffer; + case UsbLogLevel::None: + libusb_set_debug(libusbContext, LIBUSB_LOG_LEVEL_NONE); + break; - // End file transfer - FileTransferPacket *fileTransferPacket = new FileTransferPacket(FileTransferPacket::kRequestEnd); - success = SendPacket(fileTransferPacket); - delete fileTransferPacket; + case UsbLogLevel::Error: + libusb_set_debug(libusbContext, LIBUSB_LOG_LEVEL_ERROR); + break; - if (!success) - { - Interface::PrintError("Failed to send request to end dump transfer!\n"); - return (false); - } + case UsbLogLevel::Warning: + libusb_set_debug(libusbContext, LIBUSB_LOG_LEVEL_WARNING); + break; - ResponsePacket *responsePacket = new ResponsePacket(ResponsePacket::kResponseTypeFileTransfer); - success = ReceivePacket(responsePacket); - delete responsePacket; + case UsbLogLevel::Info: + libusb_set_debug(libusbContext, LIBUSB_LOG_LEVEL_INFO); + break; - if (!success) - { - Interface::PrintError("Failed to receive end dump transfer verification!\n"); - return (false); + case UsbLogLevel::Debug: + libusb_set_debug(libusbContext, LIBUSB_LOG_LEVEL_DEBUG); + break; + } } - - return (true); } diff --git a/heimdall/source/BridgeManager.h b/heimdall/source/BridgeManager.h index 2978340..4402710 100644 --- a/heimdall/source/BridgeManager.h +++ b/heimdall/source/BridgeManager.h @@ -21,6 +21,9 @@ #ifndef BRIDGEMANAGER_H
#define BRIDGEMANAGER_H
+// libpit
+#include "libpit.h"
+
// Heimdall
#include "Heimdall.h"
@@ -81,6 +84,17 @@ namespace Heimdall kPidGalaxyCamera = 0x6860 // Is this necessary?
};
+ enum class UsbLogLevel
+ {
+ None = 0,
+ Error,
+ Warning,
+ Info,
+ Debug,
+
+ Default = Error
+ };
+
private:
static const DeviceIdentifier supportedDevices[kSupportedDeviceCount];
@@ -109,13 +123,14 @@ namespace Heimdall unsigned int fileTransferPacketSize;
unsigned int fileTransferSequenceTimeout;
+ UsbLogLevel usbLogLevel;
+
int FindDeviceInterface(void);
bool ClaimDeviceInterface(void);
bool SetupDeviceInterface(void);
void ReleaseDeviceInterface(void);
- bool CheckProtocol(void) const;
- bool InitialiseProtocol(void) const;
+ bool InitialiseProtocol(void);
public:
@@ -123,7 +138,7 @@ namespace Heimdall ~BridgeManager();
bool DetectDevice(void);
- int Initialise(void);
+ int Initialise(bool resume);
bool BeginSession(void);
bool EndSession(bool reboot) const;
@@ -133,12 +148,18 @@ namespace Heimdall bool RequestDeviceType(unsigned int request, int *result) const;
- bool SendPitFile(FILE *file) const;
+ bool SendPitData(const libpit::PitData *pitData) const;
int ReceivePitFile(unsigned char **pitBuffer) const;
int DownloadPitFile(unsigned char **pitBuffer) const; // Thin wrapper around ReceivePitFile() with additional logging.
bool SendFile(FILE *file, unsigned int destination, unsigned int deviceType, unsigned int fileIdentifier = 0xFFFFFFFF) const;
- bool ReceiveDump(unsigned int chipType, unsigned int chipId, FILE *file) const;
+
+ void SetUsbLogLevel(UsbLogLevel usbLogLevel);
+
+ UsbLogLevel GetUsbLogLevel(void) const
+ {
+ return usbLogLevel;
+ }
bool IsVerbose(void) const
{
diff --git a/heimdall/source/ClosePcScreenAction.cpp b/heimdall/source/ClosePcScreenAction.cpp index a7de9d9..1c53ffe 100644 --- a/heimdall/source/ClosePcScreenAction.cpp +++ b/heimdall/source/ClosePcScreenAction.cpp @@ -25,11 +25,13 @@ #include "Heimdall.h" #include "Interface.h" +using namespace std; using namespace Heimdall; const char *ClosePcScreenAction::usage = "Action: close-pc-screen\n\ Arguments: [--verbose] [--no-reboot] [--stdout-errors] [--delay <ms>]\n\ -Description: Attempts to get rid off the \"connect phone to PC\" screen.\n"; + [--usb-log-level <none/error/warning/debug>]\n\ +Description: Attempts to get rid off the \"connect phone to PC\" screen.\n"; // TODO: usb-log-level int ClosePcScreenAction::Execute(int argc, char **argv) { @@ -37,9 +39,11 @@ int ClosePcScreenAction::Execute(int argc, char **argv) map<string, ArgumentType> argumentTypes; argumentTypes["no-reboot"] = kArgumentTypeFlag; + argumentTypes["resume"] = kArgumentTypeFlag; argumentTypes["delay"] = kArgumentTypeUnsignedInteger; argumentTypes["verbose"] = kArgumentTypeFlag; argumentTypes["stdout-errors"] = kArgumentTypeFlag; + argumentTypes["usb-log-level"] = kArgumentTypeString; Arguments arguments(argumentTypes); @@ -50,8 +54,44 @@ int ClosePcScreenAction::Execute(int argc, char **argv) } const UnsignedIntegerArgument *communicationDelayArgument = static_cast<const UnsignedIntegerArgument *>(arguments.GetArgument("delay")); + const StringArgument *usbLogLevelArgument = static_cast<const StringArgument *>(arguments.GetArgument("usb-log-level")); + + BridgeManager::UsbLogLevel usbLogLevel = BridgeManager::UsbLogLevel::Default; + + if (usbLogLevelArgument) + { + const string& usbLogLevelString = usbLogLevelArgument->GetValue(); + + if (usbLogLevelString.compare("none") == 0 || usbLogLevelString.compare("NONE") == 0) + { + usbLogLevel = BridgeManager::UsbLogLevel::None; + } + else if (usbLogLevelString.compare("error") == 0 || usbLogLevelString.compare("ERROR") == 0) + { + usbLogLevel = BridgeManager::UsbLogLevel::Error; + } + else if (usbLogLevelString.compare("warning") == 0 || usbLogLevelString.compare("WARNING") == 0) + { + usbLogLevel = BridgeManager::UsbLogLevel::Warning; + } + else if (usbLogLevelString.compare("info") == 0 || usbLogLevelString.compare("INFO") == 0) + { + usbLogLevel = BridgeManager::UsbLogLevel::Info; + } + else if (usbLogLevelString.compare("debug") == 0 || usbLogLevelString.compare("DEBUG") == 0) + { + usbLogLevel = BridgeManager::UsbLogLevel::Debug; + } + else + { + Interface::Print("Unknown USB log level: %s\n\n", usbLogLevelString.c_str()); + Interface::Print(ClosePcScreenAction::usage); + return (0); + } + } bool reboot = arguments.GetArgument("no-reboot") == nullptr; + bool resume = arguments.GetArgument("resume") != nullptr; bool verbose = arguments.GetArgument("verbose") != nullptr; if (arguments.GetArgument("stdout-errors") != nullptr) @@ -70,8 +110,9 @@ int ClosePcScreenAction::Execute(int argc, char **argv) communicationDelay = communicationDelayArgument->GetValue(); BridgeManager *bridgeManager = new BridgeManager(verbose, communicationDelay); + bridgeManager->SetUsbLogLevel(usbLogLevel); - if (bridgeManager->Initialise() != BridgeManager::kInitialiseSucceeded || !bridgeManager->BeginSession()) + if (bridgeManager->Initialise(resume) != BridgeManager::kInitialiseSucceeded || !bridgeManager->BeginSession()) { delete bridgeManager; return (1); diff --git a/heimdall/source/DetectAction.cpp b/heimdall/source/DetectAction.cpp index 319433f..c5b4eb6 100644 --- a/heimdall/source/DetectAction.cpp +++ b/heimdall/source/DetectAction.cpp @@ -25,10 +25,12 @@ #include "Heimdall.h" #include "Interface.h" +using namespace std; using namespace Heimdall; const char *DetectAction::usage = "Action: detect\n\ Arguments: [--verbose] [--stdout-errors]\n\ + [--usb-log-level <none/error/warning/debug>]\n\ Description: Indicates whether or not a download mode device can be detected.\n"; int DetectAction::Execute(int argc, char **argv) @@ -38,6 +40,7 @@ int DetectAction::Execute(int argc, char **argv) map<string, ArgumentType> argumentTypes; argumentTypes["verbose"] = kArgumentTypeFlag; argumentTypes["stdout-errors"] = kArgumentTypeFlag; + argumentTypes["usb-log-level"] = kArgumentTypeString; Arguments arguments(argumentTypes); @@ -52,9 +55,46 @@ int DetectAction::Execute(int argc, char **argv) if (arguments.GetArgument("stdout-errors") != nullptr) Interface::SetStdoutErrors(true); + const StringArgument *usbLogLevelArgument = static_cast<const StringArgument *>(arguments.GetArgument("usb-log-level")); + + BridgeManager::UsbLogLevel usbLogLevel = BridgeManager::UsbLogLevel::Default; + + if (usbLogLevelArgument) + { + const string& usbLogLevelString = usbLogLevelArgument->GetValue(); + + if (usbLogLevelString.compare("none") == 0 || usbLogLevelString.compare("NONE") == 0) + { + usbLogLevel = BridgeManager::UsbLogLevel::None; + } + else if (usbLogLevelString.compare("error") == 0 || usbLogLevelString.compare("ERROR") == 0) + { + usbLogLevel = BridgeManager::UsbLogLevel::Error; + } + else if (usbLogLevelString.compare("warning") == 0 || usbLogLevelString.compare("WARNING") == 0) + { + usbLogLevel = BridgeManager::UsbLogLevel::Warning; + } + else if (usbLogLevelString.compare("info") == 0 || usbLogLevelString.compare("INFO") == 0) + { + usbLogLevel = BridgeManager::UsbLogLevel::Info; + } + else if (usbLogLevelString.compare("debug") == 0 || usbLogLevelString.compare("DEBUG") == 0) + { + usbLogLevel = BridgeManager::UsbLogLevel::Debug; + } + else + { + Interface::Print("Unknown USB log level: %s\n\n", usbLogLevelString.c_str()); + Interface::Print(DetectAction::usage); + return (0); + } + } + // Download PIT file from device. BridgeManager *bridgeManager = new BridgeManager(verbose); + bridgeManager->SetUsbLogLevel(usbLogLevel); bool detected = bridgeManager->DetectDevice(); diff --git a/heimdall/source/DownloadPitAction.cpp b/heimdall/source/DownloadPitAction.cpp index b4b81a9..744ba56 100644 --- a/heimdall/source/DownloadPitAction.cpp +++ b/heimdall/source/DownloadPitAction.cpp @@ -28,11 +28,12 @@ #include "Heimdall.h" #include "Interface.h" +using namespace std; using namespace Heimdall; const char *DownloadPitAction::usage = "Action: download-pit\n\ Arguments: --output <filename> [--verbose] [--no-reboot] [--stdout-errors]\n\ - [--delay <ms>]\n\ + [--delay <ms>] [--usb-log-level <none/error/warning/debug>]\n\ Description: Downloads the connected device's PIT file to the specified\n\ output file.\n"; @@ -43,9 +44,11 @@ int DownloadPitAction::Execute(int argc, char **argv) map<string, ArgumentType> argumentTypes; argumentTypes["output"] = kArgumentTypeString; argumentTypes["no-reboot"] = kArgumentTypeFlag; + argumentTypes["resume"] = kArgumentTypeFlag; argumentTypes["delay"] = kArgumentTypeUnsignedInteger; argumentTypes["verbose"] = kArgumentTypeFlag; argumentTypes["stdout-errors"] = kArgumentTypeFlag; + argumentTypes["usb-log-level"] = kArgumentTypeString; Arguments arguments(argumentTypes); @@ -67,11 +70,48 @@ int DownloadPitAction::Execute(int argc, char **argv) const UnsignedIntegerArgument *communicationDelayArgument = static_cast<const UnsignedIntegerArgument *>(arguments.GetArgument("delay")); bool reboot = arguments.GetArgument("no-reboot") == nullptr; + bool resume = arguments.GetArgument("resume") != nullptr; bool verbose = arguments.GetArgument("verbose") != nullptr; if (arguments.GetArgument("stdout-errors") != nullptr) Interface::SetStdoutErrors(true); + const StringArgument *usbLogLevelArgument = static_cast<const StringArgument *>(arguments.GetArgument("usb-log-level")); + + BridgeManager::UsbLogLevel usbLogLevel = BridgeManager::UsbLogLevel::Default; + + if (usbLogLevelArgument) + { + const string& usbLogLevelString = usbLogLevelArgument->GetValue(); + + if (usbLogLevelString.compare("none") == 0 || usbLogLevelString.compare("NONE") == 0) + { + usbLogLevel = BridgeManager::UsbLogLevel::None; + } + else if (usbLogLevelString.compare("error") == 0 || usbLogLevelString.compare("ERROR") == 0) + { + usbLogLevel = BridgeManager::UsbLogLevel::Error; + } + else if (usbLogLevelString.compare("warning") == 0 || usbLogLevelString.compare("WARNING") == 0) + { + usbLogLevel = BridgeManager::UsbLogLevel::Warning; + } + else if (usbLogLevelString.compare("info") == 0 || usbLogLevelString.compare("INFO") == 0) + { + usbLogLevel = BridgeManager::UsbLogLevel::Info; + } + else if (usbLogLevelString.compare("debug") == 0 || usbLogLevelString.compare("DEBUG") == 0) + { + usbLogLevel = BridgeManager::UsbLogLevel::Debug; + } + else + { + Interface::Print("Unknown USB log level: %s\n\n", usbLogLevelString.c_str()); + Interface::Print(DownloadPitAction::usage); + return (0); + } + } + // Info Interface::PrintReleaseInfo(); @@ -96,8 +136,9 @@ int DownloadPitAction::Execute(int argc, char **argv) communicationDelay = communicationDelayArgument->GetValue(); BridgeManager *bridgeManager = new BridgeManager(verbose, communicationDelay); + bridgeManager->SetUsbLogLevel(usbLogLevel); - if (bridgeManager->Initialise() != BridgeManager::kInitialiseSucceeded || !bridgeManager->BeginSession()) + if (bridgeManager->Initialise(resume) != BridgeManager::kInitialiseSucceeded || !bridgeManager->BeginSession()) { fclose(outputPitFile); delete bridgeManager; diff --git a/heimdall/source/DumpAction.cpp b/heimdall/source/DumpAction.cpp deleted file mode 100644 index 38ccbf9..0000000 --- a/heimdall/source/DumpAction.cpp +++ /dev/null @@ -1,158 +0,0 @@ -/* Copyright (c) 2010-2012 Benjamin Dobell, Glass Echidna - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE.*/ - -// C Standard Library -#include <stdio.h> - -// Heimdall -#include "Arguments.h" -#include "BridgeManager.h" -#include "DumpAction.h" -#include "Heimdall.h" -#include "Interface.h" - -using namespace Heimdall; - -const char *DumpAction::usage = "Action: dump\n\ -Arguments: --chip-type <NAND | RAM> --chip-id <integer> --output <filename>\n\ - [--verbose] [--no-reboot] [--stdout-errors] [--delay <ms>]\n\ -Description: Attempts to dump data from the phone corresponding to the\n\ - specified chip type and chip ID.\n\ -NOTE: Galaxy S phones don't appear to properly support this functionality.\n"; - -int DumpAction::Execute(int argc, char **argv) -{ - // Handle arguments - - map<string, ArgumentType> argumentTypes; - - argumentTypes["chip-type"] = kArgumentTypeString; - argumentTypes["chip-id"] = kArgumentTypeUnsignedInteger; - argumentTypes["output"] = kArgumentTypeString; - - argumentTypes["no-reboot"] = kArgumentTypeFlag; - argumentTypes["delay"] = kArgumentTypeUnsignedInteger; - argumentTypes["verbose"] = kArgumentTypeFlag; - argumentTypes["stdout-errors"] = kArgumentTypeFlag; - - Arguments arguments(argumentTypes); - - if (!arguments.ParseArguments(argc, argv, 2)) - { - Interface::Print(DumpAction::usage); - return (0); - } - - const StringArgument *chipTypeArgument = static_cast<const StringArgument *>(arguments.GetArgument("chip-type")); - const UnsignedIntegerArgument *chipIdArgument = static_cast<const UnsignedIntegerArgument *>(arguments.GetArgument("chip-id")); - const StringArgument *outputArgument = static_cast<const StringArgument *>(arguments.GetArgument("output")); - - if (!outputArgument) - { - Interface::Print("Output file was not specified.\n\n"); - Interface::Print(DumpAction::usage); - return (false); - } - - if (!chipTypeArgument) - { - Interface::Print("You must specify a chip type.\n\n"); - Interface::Print(DumpAction::usage); - return (false); - } - - if (!(chipTypeArgument->GetValue() == "RAM" || chipTypeArgument->GetValue() == "ram" || chipTypeArgument->GetValue() == "NAND" - || chipTypeArgument->GetValue() == "nand")) - { - Interface::Print("Unknown chip type: %s.\n\n", chipTypeArgument->GetValue().c_str()); - Interface::Print(DumpAction::usage); - return (false); - } - - if (!chipIdArgument) - { - Interface::Print("You must specify a chip ID.\n\n"); - Interface::Print(DumpAction::usage); - return (false); - } - - const UnsignedIntegerArgument *communicationDelayArgument = static_cast<const UnsignedIntegerArgument *>(arguments.GetArgument("delay")); - - bool reboot = arguments.GetArgument("no-reboot") == nullptr; - bool verbose = arguments.GetArgument("verbose") != nullptr; - - if (arguments.GetArgument("stdout-errors") != nullptr) - Interface::SetStdoutErrors(true); - - // Open output file - - const char *outputFilename = outputArgument->GetValue().c_str(); - FILE *dumpFile = fopen(outputFilename, "wb"); - - if (!dumpFile) - { - Interface::PrintError("Failed to open file \"%s\"\n", outputFilename); - return (1); - } - - // Info - - Interface::PrintReleaseInfo(); - Sleep(1000); - - // Dump - - int communicationDelay = BridgeManager::kCommunicationDelayDefault; - - if (communicationDelayArgument) - communicationDelay = communicationDelayArgument->GetValue(); - - BridgeManager *bridgeManager = new BridgeManager(verbose, communicationDelay); - - if (bridgeManager->Initialise() != BridgeManager::kInitialiseSucceeded || !bridgeManager->BeginSession()) - { - fclose(dumpFile); - delete bridgeManager; - return (1); - } - - int chipType = 0; - - if (chipTypeArgument->GetValue() == "NAND" || chipTypeArgument->GetValue() == "nand") - chipType = 1; - - bool success = bridgeManager->ReceiveDump(chipType, chipIdArgument->GetValue(), dumpFile); - fclose(dumpFile); - - if (!bridgeManager->EndSession(reboot)) - success = false; - - delete bridgeManager; - - if (success) - { - Interface::Print("Attempt complete\n"); - return (0); - } - else - { - return (1); - } -} diff --git a/heimdall/source/DumpAction.h b/heimdall/source/DumpAction.h deleted file mode 100644 index eb97bca..0000000 --- a/heimdall/source/DumpAction.h +++ /dev/null @@ -1,34 +0,0 @@ -/* Copyright (c) 2010-2012 Benjamin Dobell, Glass Echidna - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE.*/ - -#ifndef DUMPACTION_H -#define DUMPACTION_H - -namespace Heimdall -{ - namespace DumpAction - { - extern const char *usage; - - int Execute(int argc, char **argv); - }; -} - -#endif diff --git a/heimdall/source/FlashAction.cpp b/heimdall/source/FlashAction.cpp index fad4df7..b5f69f2 100644 --- a/heimdall/source/FlashAction.cpp +++ b/heimdall/source/FlashAction.cpp @@ -33,36 +33,37 @@ #include "TotalBytesPacket.h" #include "Utility.h" +using namespace std; +using namespace libpit; using namespace Heimdall; const char *FlashAction::usage = "Action: flash\n\ Arguments:\n\ - --repartition --pit <filename> [--factoryfs <filename>]\n\ - [--cache <filename>] [--dbdata <filename>] [--primary-boot <filename>]\n\ - [--secondary-boot <filename>] [--param <filename>] [--kernel <filename>]\n\ - [--modem <filename>] [--radio <filename>] [--normal-boot <filename>]\n\ - [--system <filename>] [--user-data <filename>] [--fota <filename>]\n\ - [--hidden <filename>] [--movinand <filename>] [--data <filename>]\n\ - [--ums <filename>] [--emmc <filename>]\n\ - [--<partition identifier> <filename>]\n\ - [--<partition name> <filename>]\n\ + --repartition --pit <filename>\n\ + --<partition name>|--<partition identifier> <filename> [...]\n\ [--verbose] [--no-reboot] [--stdout-errors] [--delay <ms>]\n\ + [--usb-log-level <none/error/warning/debug>]\n\ or:\n\ - [--factoryfs <filename>] [--cache <filename>] [--dbdata <filename>]\n\ - [--primary-boot <filename>] [--secondary-boot <filename>]\n\ - [--secondary-boot-backup <filename>] [--param <filename>]\n\ - [--kernel <filename>] [--recovery <filename>] [--efs <filename>]\n\ - [--modem <filename>] [--radio <filename>] [--normal-boot <filename>]\n\ - [--system <filename>] [--user-data <filename>] [--fota <filename>]\n\ - [--hidden <filename>] [--movinand <filename>] [--data <filename>]\n\ - [--ums <filename>] [--emmc <filename>] [--pit <filename>]\n\ - [--<partition identifier> <filename>]\n\ - [--<partition name> <filename>]\n\ + --<partition name>|--<partition identifier> <filename> [...]\n\ + [--pit <filename>]\n\ [--verbose] [--no-reboot] [--stdout-errors] [--delay <ms>]\n\ -Description: Flashes firmware files to your phone. Partition identifiers are\n\ - integer values, they can be obtained by executing the print-pit action.\n\ + [--usb-log-level <none/error/warning/debug>]\n\ +Description: Flashes one or more firmware files to your phone. Partition names\n\ + (or identifiers) can be obtained by executing the print-pit action.\n\ WARNING: If you're repartitioning it's strongly recommended you specify\n\ - all files at your disposal, including bootloaders.\n"; + all files at your disposal.\n"; + +struct PartitionFile +{ + const char *argumentName; + FILE *file; + + PartitionFile(const char *argumentName, FILE *file) + { + this->argumentName = argumentName; + this->file = file; + } +}; struct PartitionFlashInfo { @@ -76,85 +77,37 @@ struct PartitionFlashInfo } }; -static void buildArgumentPartitionNamesMap(map< string, vector<string> >& argumentPartitionNamesMap, map<string, string>& shortArgumentAliases) +static bool openFiles(Arguments& arguments, vector<PartitionFile>& partitionFiles, FILE *& pitFile) { - argumentPartitionNamesMap["pit"].push_back("PIT"); - argumentPartitionNamesMap["factoryfs"].push_back("FACTORYFS"); - argumentPartitionNamesMap["cache"].push_back("CACHE"); - argumentPartitionNamesMap["dbdata"].push_back("DBDATAFS"); - - argumentPartitionNamesMap["primary-boot"].push_back("IBL+PBL"); - argumentPartitionNamesMap["primary-boot"].push_back("BOOT"); - - argumentPartitionNamesMap["secondary-boot"].push_back("SBL"); - argumentPartitionNamesMap["secondary-boot"].push_back("SBL1"); - - argumentPartitionNamesMap["secondary-boot-backup"].push_back("SBL2"); - argumentPartitionNamesMap["param"].push_back("PARAM"); - argumentPartitionNamesMap["kernel"].push_back("KERNEL"); - argumentPartitionNamesMap["recovery"].push_back("RECOVERY"); - argumentPartitionNamesMap["efs"].push_back("EFS"); - argumentPartitionNamesMap["modem"].push_back("MODEM"); - argumentPartitionNamesMap["radio"].push_back("RADIO"); - argumentPartitionNamesMap["normal-boot"].push_back("NORMALBOOT"); - argumentPartitionNamesMap["system"].push_back("SYSTEM"); - argumentPartitionNamesMap["user-data"].push_back("USERDATA"); - argumentPartitionNamesMap["fota"].push_back("FOTA"); - argumentPartitionNamesMap["hidden"].push_back("HIDDEN"); - argumentPartitionNamesMap["movinand"].push_back("MOVINAND"); - argumentPartitionNamesMap["data"].push_back("DATAFS"); - argumentPartitionNamesMap["ums"].push_back("UMS.EN"); - argumentPartitionNamesMap["emmc"].push_back("GANG"); + // Open PIT file - shortArgumentAliases["pit"] = "pit"; - shortArgumentAliases["fs"] = "factoryfs"; - shortArgumentAliases["cache"] = "cache"; - shortArgumentAliases["db"] = "dbdata"; - shortArgumentAliases["boot"] = "primary-boot"; - shortArgumentAliases["sbl"] = "secondary-boot"; - shortArgumentAliases["sbl2"] = "secondary-boot-backup"; - shortArgumentAliases["param"] = "param"; - shortArgumentAliases["z"] = "kernel"; - shortArgumentAliases["rec"] = "recovery"; - shortArgumentAliases["efs"] = "efs"; - shortArgumentAliases["m"] = "modem"; - shortArgumentAliases["rdio"] = "radio"; - shortArgumentAliases["norm"] = "normal-boot"; - shortArgumentAliases["sys"] = "system"; - shortArgumentAliases["udata"] = "user-data"; - shortArgumentAliases["fota"] = "fota"; - shortArgumentAliases["hide"] = "hidden"; - shortArgumentAliases["nand"] = "movinand"; - shortArgumentAliases["data"] = "data"; - shortArgumentAliases["ums"] = "ums"; - shortArgumentAliases["emmc"] = "emmc"; -} + const StringArgument *pitArgument = static_cast<const StringArgument *>(arguments.GetArgument("pit")); -static bool openFiles(Arguments& arguments, const map< string, vector<string> >& argumentPartitionNamesMap, - map<string, FILE *>& argumentFileMap) -{ - for (map<string, Argument *>::const_iterator it = arguments.GetArguments().begin(); it != arguments.GetArguments().end(); it++) + if (pitArgument) { - bool isPartitionArgument = false; - const string& argumentName = it->first; + pitFile = fopen(pitArgument->GetValue().c_str(), "rb"); - if (arguments.GetArgumentTypes().find(argumentName) == arguments.GetArgumentTypes().end()) - { - // The only way an argument could exist without being in the argument types map is if it's a wild-card. - // The "%d" wild-card refers to a partition by identifier, where as the "%s" wild-card refers to a - // partition by name. - isPartitionArgument = true; - } - else + if (!pitFile) { - // The argument wasn't a wild-card, check if it's a known partition name. - if (argumentPartitionNamesMap.find(argumentName) != argumentPartitionNamesMap.end()) - isPartitionArgument = true; + Interface::PrintError("Failed to open file \"%s\"\n", pitArgument->GetValue().c_str()); + return (false); } + } + + // Open partition files - if (isPartitionArgument) + for (vector<const Argument *>::const_iterator it = arguments.GetArguments().begin(); it != arguments.GetArguments().end(); it++) + { + bool isPartitionArgument = false; + const string& argumentName = (*it)->GetName(); + + // The only way an argument could exist without being in the argument types map is if it's a wild-card. + // The "%d" wild-card refers to a partition by identifier, where as the "%s" wild-card refers to a + // partition by name. + + if (arguments.GetArgumentTypes().find(argumentName) == arguments.GetArgumentTypes().end()) { - const StringArgument *stringArgument = static_cast<StringArgument *>(it->second); + const StringArgument *stringArgument = static_cast<const StringArgument *>(*it); FILE *file = fopen(stringArgument->GetValue().c_str(), "rb"); if (!file) @@ -163,32 +116,47 @@ static bool openFiles(Arguments& arguments, const map< string, vector<string> >& return (false); } - argumentFileMap[it->first] = file; + partitionFiles.push_back(PartitionFile(argumentName.c_str(), file)); } } return (true); } -static void closeFiles(map<string, FILE *> argumentfileMap) +static void closeFiles(vector<PartitionFile>& partitionFiles, FILE *& pitFile) { - for (map<string, FILE *>::iterator it = argumentfileMap.begin(); it != argumentfileMap.end(); it++) - fclose(it->second); + // Close PIT file - argumentfileMap.clear(); + if (pitFile) + { + fclose(pitFile); + pitFile = nullptr; + } + + // Close partition files + + for (vector<PartitionFile>::const_iterator it = partitionFiles.begin(); it != partitionFiles.end(); it++) + fclose(it->file); + + partitionFiles.clear(); } -static bool sendTotalTransferSize(BridgeManager *bridgeManager, const map<string, FILE *>& argumentFileMap, bool repartition) +static bool sendTotalTransferSize(BridgeManager *bridgeManager, const vector<PartitionFile>& partitionFiles, FILE *pitFile, bool repartition) { int totalBytes = 0; - for (map<string, FILE *>::const_iterator it = argumentFileMap.begin(); it != argumentFileMap.end(); it++) + + for (vector<PartitionFile>::const_iterator it = partitionFiles.begin(); it != partitionFiles.end(); it++) { - if (repartition || it->first != "pit") - { - fseek(it->second, 0, SEEK_END); - totalBytes += ftell(it->second); - rewind(it->second); - } + fseek(it->file, 0, SEEK_END); + totalBytes += ftell(it->file); + rewind(it->file); + } + + if (repartition) + { + fseek(pitFile, 0, SEEK_END); + totalBytes += ftell(pitFile); + rewind(pitFile); } bool success; @@ -223,108 +191,67 @@ static bool sendTotalTransferSize(BridgeManager *bridgeManager, const map<string return (true); } -static bool setupPartitionFlashInfo(const map<string, FILE *>& argumentFileMap, const map< string, vector<string> >& argumentPartitionNamesMap, - const PitData *pitData, vector<PartitionFlashInfo>& partitionFlashInfos) +static bool setupPartitionFlashInfo(const vector<PartitionFile>& partitionFiles, const PitData *pitData, vector<PartitionFlashInfo>& partitionFlashInfos) { - for (map<string, FILE *>::const_iterator it = argumentFileMap.begin(); it != argumentFileMap.end(); it++) + for (vector<PartitionFile>::const_iterator it = partitionFiles.begin(); it != partitionFiles.end(); it++) { - const string& argumentName = it->first; - FILE *partitionFile = it->second; - const PitEntry *pitEntry = nullptr; // Was the argument a partition identifier? unsigned int partitionIdentifier; - if (Utility::ParseUnsignedInt(partitionIdentifier, argumentName.c_str()) == kNumberParsingStatusSuccess) + if (Utility::ParseUnsignedInt(partitionIdentifier, it->argumentName) == kNumberParsingStatusSuccess) { pitEntry = pitData->FindEntry(partitionIdentifier); if (!pitEntry) { - Interface::PrintError("No partition with identifier \"%s\" exists in the specified PIT.\n", argumentName.c_str()); + Interface::PrintError("No partition with identifier \"%s\" exists in the specified PIT.\n", it->argumentName); return (false); } } else { - // The argument wasn't a partition identifier. Was it a known human-readable partition name? - map< string, vector<string> >::const_iterator argumentPartitionNamesIt = argumentPartitionNamesMap.find(argumentName); + // The argument must be an partition name e.g. "ZIMAGE" + pitEntry = pitData->FindEntry(it->argumentName); - if (argumentPartitionNamesIt != argumentPartitionNamesMap.end()) - { - const vector<string>& partitionNames = argumentPartitionNamesIt->second; - - // Check for the partition in the PIT file using all known names. - for (vector<string>::const_iterator nameIt = partitionNames.begin(); nameIt != partitionNames.end(); nameIt++) - { - pitEntry = pitData->FindEntry(nameIt->c_str()); - - if (pitEntry) - break; - } - - if (!pitEntry) - { - Interface::PrintError("Partition name for \"%s\" could not be located\n", argumentName.c_str()); - return (false); - } - } - else + if (!pitEntry) { - // The argument must be an actual partition name. e.g. "ZIMAGE", instead of human-readable "kernel". - pitEntry = pitData->FindEntry(argumentName.c_str()); - - if (!pitEntry) - { - Interface::PrintError("Partition \"%s\" does not exist in the specified PIT.\n", argumentName.c_str()); - return (false); - } + Interface::PrintError("Partition \"%s\" does not exist in the specified PIT.\n", it->argumentName); + return (false); } } - partitionFlashInfos.push_back(PartitionFlashInfo(pitEntry, partitionFile)); + partitionFlashInfos.push_back(PartitionFlashInfo(pitEntry, it->file)); } return (true); } -static bool isKnownPartition(const map<string, vector<string> >& argumentPartitionNamesMap, const string& argumentName, const string& partitionName) +static bool flashPitData(BridgeManager *bridgeManager, const PitData *pitData) { - const vector<string>& partitionNames = argumentPartitionNamesMap.find(argumentName)->second; + Interface::Print("Uploading PIT\n"); - for (vector<string>::const_iterator it = partitionNames.begin(); it != partitionNames.end(); it++) + if (bridgeManager->SendPitData(pitData)) { - if (partitionName == *it) - return (true); + Interface::Print("PIT upload successful\n\n"); + return (true); + } + else + { + Interface::PrintError("PIT upload failed!\n\n"); + return (false); } - - return (false); -} - -static bool isKnownBootPartition(const map<string, vector<string> >& argumentPartitionNamesMap, const char *partitionName) -{ - return (isKnownPartition(argumentPartitionNamesMap, "primary-boot", partitionName) - || isKnownPartition(argumentPartitionNamesMap, "secondary-boot", partitionName) - || isKnownPartition(argumentPartitionNamesMap, "secondary-boot-backup", partitionName) - || isKnownPartition(argumentPartitionNamesMap, "param", partitionName) - || isKnownPartition(argumentPartitionNamesMap, "normal-boot", partitionName) - || strcmp(partitionName, "SBL3") == 0 - || strcmp(partitionName, "ABOOT") == 0 - || strcmp(partitionName, "RPM") == 0 - || strcmp(partitionName, "TZ") == 0); } -static bool flashFile(BridgeManager *bridgeManager, const map< string, vector<string> >& argumentPartitionNamesMap, - const PartitionFlashInfo& partitionFlashInfo) +static bool flashFile(BridgeManager *bridgeManager, const PartitionFlashInfo& partitionFlashInfo) { - // PIT files need to be handled differently, try determine if the partition we're flashing to is a PIT partition. - - if (isKnownPartition(argumentPartitionNamesMap, "pit", partitionFlashInfo.pitEntry->GetPartitionName())) - { + if (partitionFlashInfo.pitEntry->GetBinaryType() == PitEntry::kBinaryTypeCommunicationProcessor) // Modem + { Interface::Print("Uploading %s\n", partitionFlashInfo.pitEntry->GetPartitionName()); - if (bridgeManager->SendPitFile(partitionFlashInfo.file)) + if (bridgeManager->SendFile(partitionFlashInfo.file, EndModemFileTransferPacket::kDestinationModem, + partitionFlashInfo.pitEntry->GetDeviceType())) // <-- Odin method { Interface::Print("%s upload successful\n\n", partitionFlashInfo.pitEntry->GetPartitionName()); return (true); @@ -335,128 +262,71 @@ static bool flashFile(BridgeManager *bridgeManager, const map< string, vector<st return (false); } } - else + else // partitionFlashInfo.pitEntry->GetBinaryType() == PitEntry::kBinaryTypeApplicationProcessor { - if (partitionFlashInfo.pitEntry->GetBinaryType() == PitEntry::kBinaryTypeCommunicationProcessor) // Modem - { - Interface::Print("Uploading %s\n", partitionFlashInfo.pitEntry->GetPartitionName()); + Interface::Print("Uploading %s\n", partitionFlashInfo.pitEntry->GetPartitionName()); - if (bridgeManager->SendFile(partitionFlashInfo.file, EndModemFileTransferPacket::kDestinationModem, - partitionFlashInfo.pitEntry->GetDeviceType())) // <-- Odin method - { - Interface::Print("%s upload successful\n\n", partitionFlashInfo.pitEntry->GetPartitionName()); - return (true); - } - else - { - Interface::PrintError("%s upload failed!\n\n", partitionFlashInfo.pitEntry->GetPartitionName()); - return (false); - } + if (bridgeManager->SendFile(partitionFlashInfo.file, EndPhoneFileTransferPacket::kDestinationPhone, + partitionFlashInfo.pitEntry->GetDeviceType(), partitionFlashInfo.pitEntry->GetIdentifier())) + { + Interface::Print("%s upload successful\n\n", partitionFlashInfo.pitEntry->GetPartitionName()); + return (true); } - else // partitionFlashInfo.pitEntry->GetBinaryType() == PitEntry::kBinaryTypeApplicationProcessor + else { - Interface::Print("Uploading %s\n", partitionFlashInfo.pitEntry->GetPartitionName()); - - if (bridgeManager->SendFile(partitionFlashInfo.file, EndPhoneFileTransferPacket::kDestinationPhone, - partitionFlashInfo.pitEntry->GetDeviceType(), partitionFlashInfo.pitEntry->GetIdentifier())) - { - Interface::Print("%s upload successful\n\n", partitionFlashInfo.pitEntry->GetPartitionName()); - return (true); - } - else - { - Interface::PrintError("%s upload failed!\n\n", partitionFlashInfo.pitEntry->GetPartitionName()); - return (false); - } + Interface::PrintError("%s upload failed!\n\n", partitionFlashInfo.pitEntry->GetPartitionName()); + return (false); } } - - return (true); } -static bool flashPartitions(const map<string, FILE *>& argumentFileMap, const map< string, vector<string> >& argumentPartitionNamesMap, - const PitData *pitData, BridgeManager *bridgeManager, bool repartition) +static bool flashPartitions(BridgeManager *bridgeManager, const vector<PartitionFile>& partitionFiles, const PitData *pitData, bool repartition) { vector<PartitionFlashInfo> partitionFlashInfos; // Map the files being flashed to partitions stored in the PIT file. - if (!setupPartitionFlashInfo(argumentFileMap, argumentPartitionNamesMap, pitData, partitionFlashInfos)) + if (!setupPartitionFlashInfo(partitionFiles, pitData, partitionFlashInfos)) return (false); - // If we're repartitioning then we need to flash the PIT file first. + // If we're repartitioning then we need to flash the PIT file first (if it is listed in the PIT file). if (repartition) { - vector<PartitionFlashInfo>::const_iterator it; - - for (it = partitionFlashInfos.begin(); it != partitionFlashInfos.end(); it++) - { - if (isKnownPartition(argumentPartitionNamesMap, "pit", it->pitEntry->GetPartitionName())) - { - if (!flashFile(bridgeManager, argumentPartitionNamesMap, *it)) - return (false); - - break; - } - } - - if (it == partitionFlashInfos.end()) - { - Interface::PrintError("Could not identify the PIT partition within the specified PIT file.\n\n"); + if (!flashPitData(bridgeManager, pitData)) return (false); - } } - // Flash partitions not involved in the boot process second. + // Flash partitions in the same order that arguments were specified in. for (vector<PartitionFlashInfo>::const_iterator it = partitionFlashInfos.begin(); it != partitionFlashInfos.end(); it++) { - if (!isKnownPartition(argumentPartitionNamesMap, "pit", it->pitEntry->GetPartitionName()) - && !isKnownBootPartition(argumentPartitionNamesMap, it->pitEntry->GetPartitionName())) - { - if (!flashFile(bridgeManager, argumentPartitionNamesMap, *it)) - return (false); - } - } - - // Flash boot partitions last. - for (vector<PartitionFlashInfo>::const_iterator it = partitionFlashInfos.begin(); it != partitionFlashInfos.end(); it++) - { - if (isKnownBootPartition(argumentPartitionNamesMap, it->pitEntry->GetPartitionName())) - { - if (!flashFile(bridgeManager, argumentPartitionNamesMap, *it)) - return (false); - } + if (!flashFile(bridgeManager, *it)) + return (false); } - return (true); } -static PitData *getPitData(const map<string, FILE *>& argumentFileMap, BridgeManager *bridgeManager, bool repartition) +static PitData *getPitData(BridgeManager *bridgeManager, FILE *pitFile, bool repartition) { PitData *pitData; PitData *localPitData = nullptr; // If a PIT file was passed as an argument then we must unpack it. - map<string, FILE *>::const_iterator localPitFileIt = argumentFileMap.find("pit"); - - if (localPitFileIt != argumentFileMap.end()) + if (pitFile) { - FILE *localPitFile = localPitFileIt->second; - // Load the local pit file into memory. - fseek(localPitFile, 0, SEEK_END); - long localPitFileSize = ftell(localPitFile); - rewind(localPitFile); + + fseek(pitFile, 0, SEEK_END); + long localPitFileSize = ftell(pitFile); + rewind(pitFile); unsigned char *pitFileBuffer = new unsigned char[localPitFileSize]; memset(pitFileBuffer, 0, localPitFileSize); - // dataRead is discarded, it's here to remove warnings. - int dataRead = fread(pitFileBuffer, 1, localPitFileSize, localPitFile); + int dataRead = fread(pitFileBuffer, 1, localPitFileSize, pitFile); if (dataRead > 0) { - rewind(localPitFile); + rewind(pitFile); localPitData = new PitData(); localPitData->Unpack(pitFileBuffer); @@ -513,21 +383,19 @@ int FlashAction::Execute(int argc, char **argv) // Setup argument types map<string, ArgumentType> argumentTypes; + map<string, string> shortArgumentAliases; argumentTypes["repartition"] = kArgumentTypeFlag; argumentTypes["no-reboot"] = kArgumentTypeFlag; + argumentTypes["resume"] = kArgumentTypeFlag; argumentTypes["delay"] = kArgumentTypeUnsignedInteger; argumentTypes["verbose"] = kArgumentTypeFlag; argumentTypes["stdout-errors"] = kArgumentTypeFlag; + argumentTypes["usb-log-level"] = kArgumentTypeString; - map< string, vector<string> > argumentPartitionNamesMap; - map<string, string> shortArgumentAliases; - - buildArgumentPartitionNamesMap(argumentPartitionNamesMap, shortArgumentAliases); - - for (map< string, vector<string> >::const_iterator it = argumentPartitionNamesMap.begin(); it != argumentPartitionNamesMap.end(); it++) - argumentTypes[it->first] = kArgumentTypeString; + argumentTypes["pit"] = kArgumentTypeString; + shortArgumentAliases["pit"] = "pit"; // Add wild-cards "%d" and "%s", for partition identifiers and partition names respectively. argumentTypes["%d"] = kArgumentTypeString; @@ -552,11 +420,48 @@ int FlashAction::Execute(int argc, char **argv) const UnsignedIntegerArgument *communicationDelayArgument = static_cast<const UnsignedIntegerArgument *>(arguments.GetArgument("delay")); bool reboot = arguments.GetArgument("no-reboot") == nullptr; + bool resume = arguments.GetArgument("resume") != nullptr; bool verbose = arguments.GetArgument("verbose") != nullptr; if (arguments.GetArgument("stdout-errors") != nullptr) Interface::SetStdoutErrors(true); + const StringArgument *usbLogLevelArgument = static_cast<const StringArgument *>(arguments.GetArgument("usb-log-level")); + + BridgeManager::UsbLogLevel usbLogLevel = BridgeManager::UsbLogLevel::Default; + + if (usbLogLevelArgument) + { + const string& usbLogLevelString = usbLogLevelArgument->GetValue(); + + if (usbLogLevelString.compare("none") == 0 || usbLogLevelString.compare("NONE") == 0) + { + usbLogLevel = BridgeManager::UsbLogLevel::None; + } + else if (usbLogLevelString.compare("error") == 0 || usbLogLevelString.compare("ERROR") == 0) + { + usbLogLevel = BridgeManager::UsbLogLevel::Error; + } + else if (usbLogLevelString.compare("warning") == 0 || usbLogLevelString.compare("WARNING") == 0) + { + usbLogLevel = BridgeManager::UsbLogLevel::Warning; + } + else if (usbLogLevelString.compare("info") == 0 || usbLogLevelString.compare("INFO") == 0) + { + usbLogLevel = BridgeManager::UsbLogLevel::Info; + } + else if (usbLogLevelString.compare("debug") == 0 || usbLogLevelString.compare("DEBUG") == 0) + { + usbLogLevel = BridgeManager::UsbLogLevel::Debug; + } + else + { + Interface::Print("Unknown USB log level: %s\n\n", usbLogLevelString.c_str()); + Interface::Print(FlashAction::usage); + return (0); + } + } + const StringArgument *pitArgument = static_cast<const StringArgument *>(arguments.GetArgument("pit")); bool repartition = arguments.GetArgument("repartition") != nullptr; @@ -569,16 +474,17 @@ int FlashAction::Execute(int argc, char **argv) } // Open files + + FILE *pitFile = nullptr; + vector<PartitionFile> partitionFiles; - map<string, FILE *> argumentFileMap; - - if (!openFiles(arguments, argumentPartitionNamesMap, argumentFileMap)) + if (!openFiles(arguments, partitionFiles, pitFile)) { - closeFiles(argumentFileMap); + closeFiles(partitionFiles, pitFile); return (1); } - if (argumentFileMap.size() == 0) + if (partitionFiles.size() == 0) { Interface::Print(FlashAction::usage); return (0); @@ -597,35 +503,36 @@ int FlashAction::Execute(int argc, char **argv) communicationDelay = communicationDelayArgument->GetValue(); BridgeManager *bridgeManager = new BridgeManager(verbose, communicationDelay); + bridgeManager->SetUsbLogLevel(usbLogLevel); - if (bridgeManager->Initialise() != BridgeManager::kInitialiseSucceeded || !bridgeManager->BeginSession()) + if (bridgeManager->Initialise(resume) != BridgeManager::kInitialiseSucceeded || !bridgeManager->BeginSession()) { - closeFiles(argumentFileMap); + closeFiles(partitionFiles, pitFile); delete bridgeManager; return (1); } - bool success = sendTotalTransferSize(bridgeManager, argumentFileMap, repartition); + bool success = sendTotalTransferSize(bridgeManager, partitionFiles, pitFile, repartition); if (success) { - PitData *pitData = getPitData(argumentFileMap, bridgeManager, repartition); + PitData *pitData = getPitData(bridgeManager, pitFile, repartition); if (pitData) - success = flashPartitions(argumentFileMap, argumentPartitionNamesMap, pitData, bridgeManager, repartition); + success = flashPartitions(bridgeManager, partitionFiles, pitData, repartition); else success = false; delete pitData; } - - closeFiles(argumentFileMap); if (!bridgeManager->EndSession(reboot)) success = false; delete bridgeManager; + + closeFiles(partitionFiles, pitFile); return (success ? 0 : 1); } diff --git a/heimdall/source/Interface.cpp b/heimdall/source/Interface.cpp index ec66480..0d9d7d9 100644 --- a/heimdall/source/Interface.cpp +++ b/heimdall/source/Interface.cpp @@ -27,7 +27,6 @@ #include "ClosePcScreenAction.h" #include "DetectAction.h" #include "DownloadPitAction.h" -#include "DumpAction.h" #include "FlashAction.h" #include "HelpAction.h" #include "InfoAction.h" @@ -43,7 +42,7 @@ using namespace Heimdall; map<string, Interface::ActionInfo> actionMap; bool stdoutErrors = false; -const char *version = "v1.4 RC2"; +const char *version = "v1.4 RC3"; const char *actionUsage = "Usage: heimdall <action> <action arguments>\n"; const char *releaseInfo = "Heimdall %s\n\n\ @@ -64,7 +63,6 @@ void populateActionMap(void) actionMap["close-pc-screen"] = Interface::ActionInfo(&ClosePcScreenAction::Execute, ClosePcScreenAction::usage); actionMap["detect"] = Interface::ActionInfo(&DetectAction::Execute, DetectAction::usage); actionMap["download-pit"] = Interface::ActionInfo(&DownloadPitAction::Execute, DownloadPitAction::usage); - actionMap["dump"] = Interface::ActionInfo(&DumpAction::Execute, DumpAction::usage); actionMap["flash"] = Interface::ActionInfo(&FlashAction::Execute, FlashAction::usage); actionMap["help"] = Interface::ActionInfo(&HelpAction::Execute, HelpAction::usage); actionMap["info"] = Interface::ActionInfo(&InfoAction::Execute, InfoAction::usage); diff --git a/heimdall/source/Interface.h b/heimdall/source/Interface.h index ab4b538..441932a 100644 --- a/heimdall/source/Interface.h +++ b/heimdall/source/Interface.h @@ -31,9 +31,6 @@ // Heimdall #include "Heimdall.h" -using namespace std; -using namespace libpit; - namespace Heimdall { namespace Interface @@ -59,7 +56,7 @@ namespace Heimdall } ActionInfo; - const map<string, ActionInfo>& GetActionMap(void); + const std::map<std::string, ActionInfo>& GetActionMap(void); void Print(const char *format, ...); void PrintWarning(const char *format, ...); @@ -74,7 +71,7 @@ namespace Heimdall void PrintDeviceDetectionFailed(void); - void PrintPit(const PitData *pitData); + void PrintPit(const libpit::PitData *pitData); void SetStdoutErrors(bool enabled); }; diff --git a/heimdall/source/PrintPitAction.cpp b/heimdall/source/PrintPitAction.cpp index c520d1c..cdf5b4e 100644 --- a/heimdall/source/PrintPitAction.cpp +++ b/heimdall/source/PrintPitAction.cpp @@ -28,11 +28,13 @@ #include "Interface.h" #include "PrintPitAction.h" +using namespace std; +using namespace libpit; using namespace Heimdall; const char *PrintPitAction::usage = "Action: print-pit\n\ Arguments: [--file <filename>] [--verbose] [--no-reboot] [--stdout-errors]\n\ - [--delay <ms>]\n\ + [--delay <ms>] [--usb-log-level <none/error/warning/debug>]\n\ Description: Prints the contents of a PIT file in a human readable format. If\n\ a filename is not provided then Heimdall retrieves the PIT file from the \n\ connected device.\n"; @@ -44,9 +46,11 @@ int PrintPitAction::Execute(int argc, char **argv) map<string, ArgumentType> argumentTypes; argumentTypes["file"] = kArgumentTypeString; argumentTypes["no-reboot"] = kArgumentTypeFlag; + argumentTypes["resume"] = kArgumentTypeFlag; argumentTypes["delay"] = kArgumentTypeUnsignedInteger; argumentTypes["verbose"] = kArgumentTypeFlag; argumentTypes["stdout-errors"] = kArgumentTypeFlag; + argumentTypes["usb-log-level"] = kArgumentTypeString; Arguments arguments(argumentTypes); @@ -60,11 +64,48 @@ int PrintPitAction::Execute(int argc, char **argv) const UnsignedIntegerArgument *communicationDelayArgument = static_cast<const UnsignedIntegerArgument *>(arguments.GetArgument("delay")); bool reboot = arguments.GetArgument("no-reboot") == nullptr; + bool resume = arguments.GetArgument("resume") != nullptr; bool verbose = arguments.GetArgument("verbose") != nullptr; if (arguments.GetArgument("stdout-errors") != nullptr) Interface::SetStdoutErrors(true); + const StringArgument *usbLogLevelArgument = static_cast<const StringArgument *>(arguments.GetArgument("usb-log-level")); + + BridgeManager::UsbLogLevel usbLogLevel = BridgeManager::UsbLogLevel::Default; + + if (usbLogLevelArgument) + { + const string& usbLogLevelString = usbLogLevelArgument->GetValue(); + + if (usbLogLevelString.compare("none") == 0 || usbLogLevelString.compare("NONE") == 0) + { + usbLogLevel = BridgeManager::UsbLogLevel::None; + } + else if (usbLogLevelString.compare("error") == 0 || usbLogLevelString.compare("ERROR") == 0) + { + usbLogLevel = BridgeManager::UsbLogLevel::Error; + } + else if (usbLogLevelString.compare("warning") == 0 || usbLogLevelString.compare("WARNING") == 0) + { + usbLogLevel = BridgeManager::UsbLogLevel::Warning; + } + else if (usbLogLevelString.compare("info") == 0 || usbLogLevelString.compare("INFO") == 0) + { + usbLogLevel = BridgeManager::UsbLogLevel::Info; + } + else if (usbLogLevelString.compare("debug") == 0 || usbLogLevelString.compare("DEBUG") == 0) + { + usbLogLevel = BridgeManager::UsbLogLevel::Debug; + } + else + { + Interface::Print("Unknown USB log level: %s\n\n", usbLogLevelString.c_str()); + Interface::Print(PrintPitAction::usage); + return (0); + } + } + // Open file (if specified). FILE *localPitFile = nullptr; @@ -120,8 +161,9 @@ int PrintPitAction::Execute(int argc, char **argv) communicationDelay = communicationDelayArgument->GetValue(); BridgeManager *bridgeManager = new BridgeManager(verbose, communicationDelay); + bridgeManager->SetUsbLogLevel(usbLogLevel); - if (bridgeManager->Initialise() != BridgeManager::kInitialiseSucceeded || !bridgeManager->BeginSession()) + if (bridgeManager->Initialise(resume) != BridgeManager::kInitialiseSucceeded || !bridgeManager->BeginSession()) { delete bridgeManager; return (1); diff --git a/heimdall/source/SendFilePartPacket.h b/heimdall/source/SendFilePartPacket.h index 066aacb..092694a 100644 --- a/heimdall/source/SendFilePartPacket.h +++ b/heimdall/source/SendFilePartPacket.h @@ -51,6 +51,11 @@ namespace Heimdall int bytesRead = fread(data, 1, bytesToRead, file);
}
+ SendFilePartPacket(unsigned char *buffer, int size) : OutboundPacket(size)
+ {
+ memcpy(data, buffer, size);
+ }
+
void Pack(void)
{
}
|