summaryrefslogtreecommitdiffstats
path: root/heimdall
diff options
context:
space:
mode:
authorBenjamin Dobell <benjamin.dobell+git@glassechidna.com.au>2013-03-07 14:00:52 +0100
committerBenjamin Dobell <benjamin.dobell+git@glassechidna.com.au>2013-03-07 14:12:27 +0100
commitebbc3e7cd2086a9f62a857dffe9ab0bd1f5da768 (patch)
tree2267ec17efe5435887cb68169a56418acf7a9f05 /heimdall
parentPrevious libusbx fix was a red herring of sorts. Inadvertedly it did fix the (diff)
downloadHeimdall-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 'heimdall')
-rw-r--r--heimdall/heimdall.vcxproj8
-rw-r--r--heimdall/heimdall.vcxproj.filters6
-rw-r--r--heimdall/source/Arguments.cpp37
-rw-r--r--heimdall/source/Arguments.h63
-rw-r--r--heimdall/source/BridgeManager.cpp230
-rw-r--r--heimdall/source/BridgeManager.h31
-rw-r--r--heimdall/source/ClosePcScreenAction.cpp45
-rw-r--r--heimdall/source/DetectAction.cpp40
-rw-r--r--heimdall/source/DownloadPitAction.cpp45
-rw-r--r--heimdall/source/DumpAction.cpp158
-rw-r--r--heimdall/source/DumpAction.h34
-rw-r--r--heimdall/source/FlashAction.cpp451
-rw-r--r--heimdall/source/Interface.cpp4
-rw-r--r--heimdall/source/Interface.h7
-rw-r--r--heimdall/source/PrintPitAction.cpp46
-rw-r--r--heimdall/source/SendFilePartPacket.h5
16 files changed, 538 insertions, 672 deletions
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)
{
}