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["verbose"] = kArgumentTypeFlag; argumentTypes["stdout-errors"] = kArgumentTypeFlag; argumentTypes["usb-log-level"] = kArgumentTypeString; argumentTypes["pit"] = kArgumentTypeString; shortArgumentAliases["pit"] = "pit"; // Add wild-cards "%d" and "%s", for partition identifiers and partition names respectively. argumentTypes["%d"] = kArgumentTypeString; shortArgumentAliases["%d"] = "%d"; argumentTypes["%s"] = kArgumentTypeString; shortArgumentAliases["%s"] = "%s"; map<string, string> argumentAliases; argumentAliases["PIT"] = "pit"; // Map upper-case PIT argument (i.e. partition name) to known lower-case pit argument. // Handle arguments Arguments arguments(argumentTypes, shortArgumentAliases, argumentAliases); if (!arguments.ParseArguments(argc, argv, 2)) { Interface::Print(FlashAction::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) 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; if (repartition && !pitArgument) { Interface::Print("If you wish to repartition then a PIT file must be specified.\n\n"); Interface::Print(FlashAction::usage); return (0); } // Open files FILE *pitFile = nullptr; vector<PartitionFile> partitionFiles; if (!openFiles(arguments, partitionFiles, pitFile)) { closeFiles(partitionFiles, pitFile); return (1); } if (partitionFiles.size() == 0) { Interface::Print(FlashAction::usage); return (0); } // Info Interface::PrintReleaseInfo(); Sleep(1000); // Perform flash BridgeManager *bridgeManager = new BridgeManager(verbose); bridgeManager->SetUsbLogLevel(usbLogLevel); if (bridgeManager->Initialise(resume) != BridgeManager::kInitialiseSucceeded || !bridgeManager->BeginSession()) { closeFiles(partitionFiles, pitFile); delete bridgeManager; return (1); } bool success = sendTotalTransferSize(bridgeManager, partitionFiles, pitFile, repartition); if (success) { PitData *pitData = getPitData(bridgeManager, pitFile, repartition); if (pitData) success = flashPartitions(bridgeManager, partitionFiles, pitData, repartition); else success = false; delete pitData; } if (!bridgeManager->EndSession(reboot)) success = false; delete bridgeManager; closeFiles(partitionFiles, pitFile); return (success ? 0 : 1); }
int main(int argc, char **argv) { map<string, string> argumentMap; int actionIndex; if (!InterfaceManager::GetArguments(argc, argv, argumentMap, &actionIndex)) { Sleep(250); return (0); } initialiseKnownPartitionNames(); if (actionIndex == InterfaceManager::kActionHelp) { InterfaceManager::Print(InterfaceManager::usage); return (0); } else if (actionIndex == InterfaceManager::kActionFlash) { if (argumentMap.find(InterfaceManager::flashArgumentNames[InterfaceManager::kFlashArgRepartition]) != argumentMap.end() && argumentMap.find(InterfaceManager::flashArgumentNames[InterfaceManager::kFlashArgPit]) == argumentMap.end()) { InterfaceManager::Print("If you wish to repartition then a PIT file must be specified.\n"); return (0); } if (argumentMap.find(InterfaceManager::flashArgumentNames[InterfaceManager::kFlashArgPit]) != argumentMap.end() && argumentMap.find(InterfaceManager::flashArgumentNames[InterfaceManager::kFlashArgRepartition]) == argumentMap.end()) { InterfaceManager::Print("A PIT file should only be used when repartitioning.\n"); return (0); } } else if (actionIndex == InterfaceManager::kActionDump) { if (argumentMap.find(InterfaceManager::dumpArgumentNames[InterfaceManager::kDumpArgOutput]) == argumentMap.end()) { InterfaceManager::Print("Output file not specified.\n\n"); InterfaceManager::Print(InterfaceManager::usage); return (0); } if (argumentMap.find(InterfaceManager::dumpArgumentNames[InterfaceManager::kDumpArgChipType]) == argumentMap.end()) { InterfaceManager::Print("You must specify a chip type.\n\n"); InterfaceManager::Print(InterfaceManager::usage); return (0); } string chipType = argumentMap.find(InterfaceManager::dumpArgumentNames[InterfaceManager::kDumpArgChipType])->second; if (!(chipType == "RAM" || chipType == "ram" || chipType == "NAND" || chipType == "nand")) { InterfaceManager::Print("Unknown chip type: %s.\n\n", chipType.c_str()); InterfaceManager::Print(InterfaceManager::usage); return (0); } if (argumentMap.find(InterfaceManager::dumpArgumentNames[InterfaceManager::kDumpArgChipId]) == argumentMap.end()) { InterfaceManager::Print("You must specify a Chip ID.\n\n"); InterfaceManager::Print(InterfaceManager::usage); return (0); } int chipId = atoi(argumentMap.find(InterfaceManager::dumpArgumentNames[InterfaceManager::kDumpArgChipId])->second.c_str()); if (chipId < 0) { InterfaceManager::Print("Chip ID must be a non-negative integer.\n"); return (0); } } InterfaceManager::Print("\nHeimdall v1.2.0, Copyright (c) 2010-2011, Benjamin Dobell, Glass Echidna\n"); InterfaceManager::Print("http://www.glassechidna.com.au\n\n"); InterfaceManager::Print("This software is provided free of charge. Copying and redistribution is\nencouraged.\n\n"); InterfaceManager::Print("If you appreciate this software and you would like to support future\ndevelopment please consider donating:\n"); InterfaceManager::Print("http://www.glassechidna.com.au/donate/\n\n"); Sleep(1000); bool verbose = argumentMap.find(InterfaceManager::commonArgumentNames[InterfaceManager::kCommonArgVerbose]) != argumentMap.end(); bool noReboot = argumentMap.find(InterfaceManager::commonArgumentNames[InterfaceManager::kCommonArgNoReboot]) != argumentMap.end(); int communicationDelay = BridgeManager::kCommunicationDelayDefault; if (argumentMap.find(InterfaceManager::commonArgumentNames[InterfaceManager::kCommonArgDelay]) != argumentMap.end()) communicationDelay = atoi(argumentMap.find(InterfaceManager::commonArgumentNames[InterfaceManager::kCommonArgDelay])->second.c_str()); BridgeManager *bridgeManager = new BridgeManager(verbose, communicationDelay); if (!bridgeManager->Initialise()) { delete bridgeManager; return (-2); } bool success; switch (actionIndex) { case InterfaceManager::kActionFlash: { map<string, FILE *> argumentFileMap; // We open the files before doing anything else to ensure they exist. if (!openFiles(argumentMap, argumentFileMap)) { closeFiles(argumentFileMap); delete bridgeManager; return (0); } if (!bridgeManager->BeginSession()) { closeFiles(argumentFileMap); delete bridgeManager; return (-1); } bool repartition = argumentMap.find(InterfaceManager::flashArgumentNames[InterfaceManager::kFlashArgRepartition]) != argumentMap.end(); success = attemptFlash(bridgeManager, argumentFileMap, repartition); if (noReboot) success = bridgeManager->EndSession() && success; else success = bridgeManager->EndSession() && bridgeManager->RebootDevice() && success; closeFiles(argumentFileMap); break; } case InterfaceManager::kActionClosePcScreen: { if (!bridgeManager->BeginSession()) { delete bridgeManager; return (-1); } InterfaceManager::Print("Attempting to close connect to pc screen...\n"); if (noReboot) success = bridgeManager->EndSession(); else success = bridgeManager->EndSession() && bridgeManager->RebootDevice(); if (success) InterfaceManager::Print("Attempt complete\n"); break; } case InterfaceManager::kActionDump: { const char *outputFilename = argumentMap.find(InterfaceManager::dumpArgumentNames[InterfaceManager::kDumpArgOutput])->second.c_str(); FILE *dumpFile = fopen(outputFilename, "wb"); if (!dumpFile) { InterfaceManager::PrintError("Failed to open file \"%s\"\n", outputFilename); delete bridgeManager; return (-1); } int chipType = 0; string chipTypeName = argumentMap.find(InterfaceManager::dumpArgumentNames[InterfaceManager::kDumpArgChipType])->second; if (chipTypeName == "NAND" || chipTypeName == "nand") chipType = 1; int chipId = atoi(argumentMap.find(InterfaceManager::dumpArgumentNames[InterfaceManager::kDumpArgChipId])->second.c_str()); if (!bridgeManager->BeginSession()) { fclose(dumpFile); delete bridgeManager; return (-1); } success = bridgeManager->ReceiveDump(chipType, chipId, dumpFile); fclose(dumpFile); if (noReboot) success = bridgeManager->EndSession() && success; else success = bridgeManager->EndSession() && bridgeManager->RebootDevice() && success; break; } case InterfaceManager::kActionPrintPit: { if (!bridgeManager->BeginSession()) { delete bridgeManager; return (-1); } unsigned char *devicePit; if (downloadPitFile(bridgeManager, &devicePit) < -1) { if (!bridgeManager->EndSession()) return (-1); if (!noReboot) bridgeManager->RebootDevice(); delete bridgeManager; return (-1); } PitData *pitData = new PitData(); if (pitData->Unpack(devicePit)) { pitData->Print(); success = true; } else { InterfaceManager::PrintError("Failed to unpack device's PIT file!\n"); success = false; } delete pitData; if (noReboot) success = bridgeManager->EndSession() && success; else success = bridgeManager->EndSession() && bridgeManager->RebootDevice() && success; break; } } delete bridgeManager; return ((success) ? 0 : -1); }