summaryrefslogtreecommitdiffstats
path: root/heimdall/source/FlashAction.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--heimdall/source/FlashAction.cpp451
1 files changed, 179 insertions, 272 deletions
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);
}