From ebbc3e7cd2086a9f62a857dffe9ab0bd1f5da768 Mon Sep 17 00:00:00 2001 From: Benjamin Dobell Date: Fri, 8 Mar 2013 00:00:52 +1100 Subject: - Removed legacy command line hard-coded partition name parameters. - As a result of the above two points, there are no "known boot partitions", and hence boot partitions are not automatically flashed last. - Made partitions flash in the order in order in which partition arguments are specified. Hence, it's recommended that you specify boot partitions last. - Added --usb-level argument that can be used for debugging libusbx, or flashing issues in general. - Removed generally non-functional firmware dumping behaviour. - Removed auto-resume functionality - Although this feature was definitely nice to have; I believe it may be responsible for flashing compatibility issues for a variety of devices. - As a result of the above. In order perform another action after a --no-reboot action, you must provide the --resume flag. - Heimdall Frontend also has support for specifying the --resume flag via a GUI. Heimdall Frontend also tries to keep track of your actions and enable "Resume" automatically after a "No Reboot" action. - Refactored quite a few of the actions, and code responsible for flashing (particularly PIT file flashing). - Bumped version to 1.4RC3 *however* this commit is not yet an official release candidate. It's still a WIP. In particular build files still have not been updated for Linux and OS X. --- heimdall/source/FlashAction.cpp | 451 ++++++++++++++++------------------------ 1 file changed, 179 insertions(+), 272 deletions(-) (limited to 'heimdall/source/FlashAction.cpp') 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 [--factoryfs ]\n\ - [--cache ] [--dbdata ] [--primary-boot ]\n\ - [--secondary-boot ] [--param ] [--kernel ]\n\ - [--modem ] [--radio ] [--normal-boot ]\n\ - [--system ] [--user-data ] [--fota ]\n\ - [--hidden ] [--movinand ] [--data ]\n\ - [--ums ] [--emmc ]\n\ - [-- ]\n\ - [-- ]\n\ + --repartition --pit \n\ + --|-- [...]\n\ [--verbose] [--no-reboot] [--stdout-errors] [--delay ]\n\ + [--usb-log-level ]\n\ or:\n\ - [--factoryfs ] [--cache ] [--dbdata ]\n\ - [--primary-boot ] [--secondary-boot ]\n\ - [--secondary-boot-backup ] [--param ]\n\ - [--kernel ] [--recovery ] [--efs ]\n\ - [--modem ] [--radio ] [--normal-boot ]\n\ - [--system ] [--user-data ] [--fota ]\n\ - [--hidden ] [--movinand ] [--data ]\n\ - [--ums ] [--emmc ] [--pit ]\n\ - [-- ]\n\ - [-- ]\n\ + --|-- [...]\n\ + [--pit ]\n\ [--verbose] [--no-reboot] [--stdout-errors] [--delay ]\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 ]\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 >& argumentPartitionNamesMap, map& shortArgumentAliases) +static bool openFiles(Arguments& arguments, vector& 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(arguments.GetArgument("pit")); -static bool openFiles(Arguments& arguments, const map< string, vector >& argumentPartitionNamesMap, - map& argumentFileMap) -{ - for (map::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_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(it->second); + const StringArgument *stringArgument = static_cast(*it); FILE *file = fopen(stringArgument->GetValue().c_str(), "rb"); if (!file) @@ -163,32 +116,47 @@ static bool openFiles(Arguments& arguments, const map< string, vector >& return (false); } - argumentFileMap[it->first] = file; + partitionFiles.push_back(PartitionFile(argumentName.c_str(), file)); } } return (true); } -static void closeFiles(map argumentfileMap) +static void closeFiles(vector& partitionFiles, FILE *& pitFile) { - for (map::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::const_iterator it = partitionFiles.begin(); it != partitionFiles.end(); it++) + fclose(it->file); + + partitionFiles.clear(); } -static bool sendTotalTransferSize(BridgeManager *bridgeManager, const map& argumentFileMap, bool repartition) +static bool sendTotalTransferSize(BridgeManager *bridgeManager, const vector& partitionFiles, FILE *pitFile, bool repartition) { int totalBytes = 0; - for (map::const_iterator it = argumentFileMap.begin(); it != argumentFileMap.end(); it++) + + for (vector::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& argumentFileMap, const map< string, vector >& argumentPartitionNamesMap, - const PitData *pitData, vector& partitionFlashInfos) +static bool setupPartitionFlashInfo(const vector& partitionFiles, const PitData *pitData, vector& partitionFlashInfos) { - for (map::const_iterator it = argumentFileMap.begin(); it != argumentFileMap.end(); it++) + for (vector::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 >::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& partitionNames = argumentPartitionNamesIt->second; - - // Check for the partition in the PIT file using all known names. - for (vector::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 >& argumentPartitionNamesMap, const string& argumentName, const string& partitionName) +static bool flashPitData(BridgeManager *bridgeManager, const PitData *pitData) { - const vector& partitionNames = argumentPartitionNamesMap.find(argumentName)->second; + Interface::Print("Uploading PIT\n"); - for (vector::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 >& 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 >& 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, vectorGetBinaryType() == 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& argumentFileMap, const map< string, vector >& argumentPartitionNamesMap, - const PitData *pitData, BridgeManager *bridgeManager, bool repartition) +static bool flashPartitions(BridgeManager *bridgeManager, const vector& partitionFiles, const PitData *pitData, bool repartition) { vector 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::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::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::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& 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::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 argumentTypes; + map 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 > argumentPartitionNamesMap; - map shortArgumentAliases; - - buildArgumentPartitionNamesMap(argumentPartitionNamesMap, shortArgumentAliases); - - for (map< string, vector >::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(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(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(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 partitionFiles; - map 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); } -- cgit v1.1