diff options
Diffstat (limited to 'heimdall/source/Interface.cpp')
-rw-r--r-- | heimdall/source/Interface.cpp | 484 |
1 files changed, 164 insertions, 320 deletions
diff --git a/heimdall/source/Interface.cpp b/heimdall/source/Interface.cpp index 4d42ad0..67f1bee 100644 --- a/heimdall/source/Interface.cpp +++ b/heimdall/source/Interface.cpp @@ -24,342 +24,108 @@ #include <stdio.h> // Heimdall +#include "ClosePcScreenAction.h" +#include "DetectAction.h" +#include "DownloadPitAction.h" +#include "DumpAction.h" +#include "FlashAction.h" +#include "HelpAction.h" +#include "InfoAction.h" #include "Heimdall.h" #include "Interface.h" +#include "PrintPitAction.h" +#include "VersionAction.h" using namespace std; using namespace libpit; using namespace Heimdall; -bool Interface::stdoutErrors = false; +map<string, Interface::ActionInfo> actionMap; +bool stdoutErrors = false; + +const char *version = "v1.4 RC1"; +const char *actionUsage = "Usage: heimdall <action> <action arguments>\n"; -const char *Interface::version = "v1.3.2"; - -const char *Interface::usage = "Usage: heimdall <action> <action arguments> <common arguments>\n\ -\n\ -Common Arguments:\n\ - [--verbose] [--no-reboot] [--stdout-errors] [--delay <ms>]\n\ -\n\ -\n\ -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>] [--normal-boot <filename>] [--system <filename>]\n\ - [--user-data <filename>] [--fota <filename>] [--hidden <filename>]\n\ - [--movinand <filename>] [--data <filename>] [--ums <filename>]\n\ - [--emmc <filename>] [--<partition identifier> <filename>]\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>] [--normal-boot <filename>] [--system <filename>]\n\ - [--user-data <filename>] [--fota <filename>] [--hidden <filename>]\n\ - [--movinand <filename>] [--data <filename>] [--ums <filename>]\n\ - [--emmc <filename>] [--<partition identifier> <filename>]\n\ -Description: Flashes firmware files to your phone.\n\ -WARNING: If you're repartitioning it's strongly recommended you specify\n\ - all files at your disposal, including bootloaders.\n\ -\n\ -Action: close-pc-screen\n\ -Description: Attempts to get rid off the \"connect phone to PC\" screen.\n\ -\n\ -Action: download-pit\n\ -Arguments: --output <filename>\n\ -Description: Downloads the connected device's PIT file to the specified\n\ - output file.\n\ -\n\ -Action: detect\n\ -Description: Indicates whether or not a download mode device can be detected.\n\ -\n\ -Action: dump\n\ -Arguments: --chip-type <NAND | RAM> --chip-id <integer> --output <filename>\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\ -\n\ -Action: print-pit\n\ -Description: Dumps the PIT file from the connected device and prints it in\n\ - a human readable format.\n\ -\n\ -Action: version\n\ -Description: Displays the version number of this binary.\n\ -\n\ -Action: help\n\ -Description: Displays this dialogue.\n"; - -const char *Interface::releaseInfo = "Heimdall %s, Copyright (c) 2010-2012, Benjamin Dobell, Glass Echidna\n\ -http://www.glassechidna.com.au\n\n\ +const char *releaseInfo = "Heimdall %s\n\n\ +Copyright (c) 2010-2012, Benjamin Dobell, Glass Echidna\n\ +http://www.glassechidna.com.au/\n\n\ This software is provided free of charge. Copying and redistribution is\nencouraged.\n\n\ If you appreciate this software and you would like to support future\ndevelopment please consider donating:\n\ http://www.glassechidna.com.au/donate/\n\n"; -const char *Interface::extraInfo = "Heimdall utilises libusb-1.0 for all USB communication:\n\ +static const char *extraInfo = "Heimdall utilises libusb-1.0 for all USB communication:\n\ http://www.libusb.org/\n\ \n\ libusb-1.0 is licensed under the LGPL-2.1:\n\ http://www.gnu.org/licenses/licenses.html#LGPL\n\n"; -// Flash arguments -string Interface::flashValueArguments[kFlashValueArgCount] = { - "-pit", "-factoryfs", "-cache", "-dbdata", "-primary-boot", "-secondary-boot", "-secondary-boot-backup", "-param", "-kernel", "-recovery", "-efs", "-modem", - "-normal-boot", "-system", "-user-data", "-fota", "-hidden", "-movinand", "-data", "-ums", "-emmc", "-%d" -}; - -string Interface::flashValueShortArguments[kFlashValueArgCount] = { - "pit", "fs", "cache", "db", "boot", "sbl", "sbl2", "param", "z", "rec", "efs", "m", - "norm", "sys", "udata", "fota", "hide", "nand", "data", "ums", "emmc", "%d" -}; - -string Interface::flashValuelessArguments[kFlashValuelessArgCount] = { - "-repartition" -}; - -string Interface::flashValuelessShortArguments[kFlashValuelessArgCount] = { - "r" -}; - -// Download PIT arguments -string Interface::downloadPitValueArguments[kDownloadPitValueArgCount] = { - "-output" -}; - -string Interface::downloadPitValueShortArguments[kDownloadPitValueArgCount] = { - "o" -}; - -// Dump arguments -string Interface::dumpValueArguments[kDumpValueArgCount] = { - "-chip-type", "-chip-id", "-output" -}; - -string Interface::dumpValueShortArguments[kDumpValueArgCount] = { - "type", "id", "out" -}; - -// Common arguments -string Interface::commonValueArguments[kCommonValueArgCount] = { - "-delay" -}; - -string Interface::commonValueShortArguments[kCommonValueArgCount] = { - "d" -}; - -string Interface::commonValuelessArguments[kCommonValuelessArgCount] = { - "-verbose", "-no-reboot", "-stdout-errors" -}; - -string Interface::commonValuelessShortArguments[kCommonValuelessArgCount] = { - "v", "nobt", "err" -}; - -Action Interface::actions[Interface::kActionCount] = { - // kActionFlash - Action("flash", flashValueArguments, flashValueShortArguments, kFlashValueArgCount, - flashValuelessArguments, flashValuelessShortArguments, kFlashValuelessArgCount), - - // kActionClosePcScreen - Action("close-pc-screen", nullptr, nullptr, kClosePcScreenValueArgCount, - nullptr, nullptr, kClosePcScreenValuelessArgCount), - - // kActionDump - Action("dump", dumpValueArguments, dumpValueShortArguments, kDumpValueArgCount, - nullptr, nullptr, kDumpValuelessArgCount), - - // kActionPrintPit - Action("print-pit", nullptr, nullptr, kPrintPitValueArgCount, - nullptr, nullptr, kPrintPitValuelessArgCount), - - // kActionVersion - Action("version", nullptr, nullptr, kVersionValueArgCount, - nullptr, nullptr, kVersionValuelessArgCount), - - // kActionHelp - Action("help", nullptr, nullptr, kHelpValueArgCount, - nullptr, nullptr, kHelpValuelessArgCount), - - // kActionDetect - Action("detect", nullptr, nullptr, kDetectValueArgCount, - nullptr, nullptr, kDetectValuelessArgCount), - - // kActionDownloadPit - Action("download-pit", downloadPitValueArguments, downloadPitValueShortArguments, kDownloadPitValueArgCount, - nullptr, nullptr, kDownloadPitValuelessArgCount), - - // kActionInfo - Action("info", nullptr, nullptr, kInfoValueArgCount, - nullptr, nullptr, kInfoValuelessArgCount) -}; - -bool Interface::GetArguments(int argc, char **argv, map<string, string>& argumentMap, int *actionIndex) +void populateActionMap(void) { - if (argc < 2) - { - Print(usage, version); - return (false); - } - - const char *actionName = argv[1]; - *actionIndex = -1; - - for (int i = 0; i < kActionCount; i++) - { - if (actions[i].name == actionName) - { - *actionIndex = i; - break; - } - } - - if (*actionIndex < 0) - { - Print("Unknown action \"%s\"\n\n", actionName); - Print(usage, version); - return (false); - } - - const Action& action = actions[*actionIndex]; - - for (int argIndex = 2; argIndex < argc; argIndex++) - { - if (*(argv[argIndex]) != '-') - { - Print(usage, version); - return (false); - } - - string argumentName = (char *)(argv[argIndex] + 1); - - // Check if the argument is a valid valueless argument - bool valid = false; - - for (unsigned int i = 0; i < action.valuelessArgumentCount; i++) - { - if (argumentName == action.valuelessArguments[i] || argumentName == action.valuelessShortArguments[i]) - { - argumentName = action.valuelessArguments[i]; - valid = true; - break; - } - } - - if (!valid) - { - // Check if it's a common valueless argument - for (unsigned int i = 0; i < kCommonValuelessArgCount; i++) - { - if (argumentName == commonValuelessArguments[i] || argumentName == commonValuelessShortArguments[i]) - { - argumentName = commonValuelessArguments[i]; - valid = true; - break; - } - } - } + 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); + actionMap["print-pit"] = Interface::ActionInfo(&PrintPitAction::Execute, PrintPitAction::usage); + actionMap["version"] = Interface::ActionInfo(&VersionAction::Execute, VersionAction::usage); +} - if (valid) - { - // The argument is valueless - argumentMap.insert(pair<string, string>(argumentName, "")); - continue; - } +const map<string, Interface::ActionInfo>& Interface::GetActionMap(void) +{ + if (actionMap.size() == 0) + populateActionMap(); - // Check if the argument is a valid value argument - for (unsigned int i = 0; i < action.valueArgumentCount; i++) - { - // Support for --<integer> and -<integer> parameters. - if (argumentName.length() > 1 && action.valueArguments[i] == "-%d") - { - if (atoi(argumentName.substr(1).c_str()) > 0 || argumentName == "-0") - { - valid = true; - break; - } - } - else if (action.valueArguments[i] == "%d") - { - if (atoi(argumentName.c_str()) > 0 || argumentName == "0") - { - argumentName = "-" + argumentName; - valid = true; - break; - } - } + return actionMap; +} - if (argumentName == action.valueArguments[i] || argumentName == action.valueShortArguments[i]) - { - argumentName = action.valueArguments[i]; - valid = true; - break; - } - } +void Interface::Print(const char *format, ...) +{ + va_list args; + va_start(args, format); - if (!valid) - { - // Check if it's a common value argument - for (unsigned int i = 0; i < kCommonValueArgCount; i++) - { - // Support for --<integer> and -<integer> parameters. - if (argumentName.length() > 1 && commonValueArguments[i] == "-%d") - { - if (atoi(argumentName.substr(1).c_str()) > 0 || argumentName == "-0") - { - valid = true; - break; - } - } - else if (commonValueArguments[i] == "%d") - { - if (atoi(argumentName.c_str()) > 0 || argumentName == "0") - { - argumentName = "-" + argumentName; - valid = true; - break; - } - } - - if (argumentName == commonValueArguments[i] || argumentName == commonValueShortArguments[i]) - { - argumentName = commonValueArguments[i]; - valid = true; - break; - } - } - } + vfprintf(stdout, format, args); + fflush(stdout); - if (!valid) - { - PrintError("\"%s\" is not a valid argument\n", argumentName.c_str()); - return (false); - } + va_end(args); + +} - argIndex++; +void Interface::PrintWarning(const char *format, ...) +{ + va_list args; + va_start(args, format); - if (argIndex >= argc) - { - PrintError("\"%s\" is missing a value\n", argumentName.c_str()); - return (false); - } + fprintf(stderr, "WARNING: "); + vfprintf(stderr, format, args); + fflush(stderr); - argumentMap.insert(pair<string, string>(argumentName, argv[argIndex])); + if (stdoutErrors) + { + fprintf(stdout, "WARNING: "); + vfprintf(stdout, format, args); + fflush(stdout); } - return (true); + va_end(args); } -void Interface::Print(const char *format, ...) +void Interface::PrintWarningSameLine(const char *format, ...) { va_list args; va_start(args, format); - vfprintf(stdout, format, args); - fflush(stdout); + vfprintf(stderr, format, args); + fflush(stderr); + + if (stdoutErrors) + { + vfprintf(stdout, format, args); + fflush(stdout); + } va_end(args); - } void Interface::PrintError(const char *format, ...) @@ -400,28 +166,33 @@ void Interface::PrintErrorSameLine(const char *format, ...) void Interface::PrintVersion(void) { - Print("%s\n", version); + Interface::Print("%s\n", version); } void Interface::PrintUsage(void) { - Print(usage); + const map<string, ActionInfo>& actionMap = Interface::GetActionMap(); + + Interface::Print(actionUsage); + + for (map<string, ActionInfo>::const_iterator it = actionMap.begin(); it != actionMap.end(); it++) + Interface::Print("\n%s", it->second.usage); } void Interface::PrintReleaseInfo(void) { - Print(releaseInfo, version); + Interface::Print(releaseInfo, version); } void Interface::PrintFullInfo(void) { - Print(releaseInfo, version); - Print(extraInfo); + Interface::Print(releaseInfo, version); + Interface::Print(extraInfo); } void Interface::PrintDeviceDetectionFailed(void) { - Print("Failed to detect compatible download-mode device.\n"); + Interface::PrintError("Failed to detect compatible download-mode device.\n"); } void Interface::PrintPit(const PitData *pitData) @@ -442,34 +213,107 @@ void Interface::PrintPit(const PitData *pitData) const PitEntry *entry = pitData->GetEntry(i); Interface::Print("\n\n--- Entry #%d ---\n", i); - Interface::Print("Unused: %s\n", (entry->GetUnused()) ? "Yes" : "No"); + Interface::Print("Binary Type: %d (", entry->GetBinaryType()); - const char *chipIdentifierText = "Unknown"; + switch (entry->GetBinaryType()) + { + case PitEntry::kBinaryTypeApplicationProcessor: + Interface::Print("AP"); + break; - Interface::Print("Chip Identifier: %d (%s)\n", entry->GetChipIdentifier()); + case PitEntry::kBinaryTypeCommunicationProcessor: + Interface::Print("CP"); + break; - Interface::Print("Partition Identifier: %d\n", entry->GetPartitionIdentifier()); + default: + Interface::Print("Unknown"); + break; + } - Interface::Print("Partition Flags: %d (", entry->GetPartitionFlags()); + Interface::Print(")\n"); - if (entry->GetPartitionFlags() & PitEntry::kPartitionFlagWrite) - Interface::Print("R/W"); + Interface::Print("Device Type: %d (", entry->GetDeviceType()); + + switch (entry->GetDeviceType()) + { + case PitEntry::kDeviceTypeOneNand: + Interface::Print("OneNAND"); + break; + + case PitEntry::kDeviceTypeFile: + Interface::Print("File/FAT"); + break; + + case PitEntry::kDeviceTypeMMC: + Interface::Print("MMC"); + break; + + case PitEntry::kDeviceTypeAll: + Interface::Print("All (?)"); + break; + + default: + Interface::Print("Unknown"); + break; + } + + Interface::Print(")\n"); + + Interface::Print("Identifier: %d\n", entry->GetIdentifier()); + + Interface::Print("Attributes: %d (", entry->GetAttributes()); + + if (entry->GetAttributes() & PitEntry::kAttributeSTL) + Interface::Print("STL "); + + if (entry->GetAttributes() & PitEntry::kAttributeWrite) + Interface::Print("Read/Write"); else - Interface::Print("R"); + Interface::Print("Read-Only"); Interface::Print(")\n"); - Interface::Print("Unknown 1: %d\n", entry->GetUnknown1()); + Interface::Print("Update Attributes: %d", entry->GetUpdateAttributes()); + + if (entry->GetUpdateAttributes()) + { + Interface::Print(" ("); + + if (entry->GetUpdateAttributes() & PitEntry::kUpdateAttributeFota) + { + if (entry->GetUpdateAttributes() & PitEntry::kUpdateAttributeSecure) + Interface::Print("FOTA, Secure"); + else + Interface::Print("FOTA"); + } + else + { + if (entry->GetUpdateAttributes() & PitEntry::kUpdateAttributeSecure) + Interface::Print("Secure"); + } + + Interface::Print(")\n"); + } + else + { + Interface::Print("\n"); + } - Interface::Print("Partition Block Size: %d\n", entry->GetPartitionBlockSize()); - Interface::Print("Partition Block Count: %d\n", entry->GetPartitionBlockCount()); + Interface::Print("Partition Block Size: %d\n", entry->GetBlockSize()); + Interface::Print("Partition Block Count: %d\n", entry->GetBlockCount()); - Interface::Print("Unknown 2: %d\n", entry->GetUnknown2()); - Interface::Print("Unknown 3: %d\n", entry->GetUnknown3()); + Interface::Print("File Offset (Obsolete): %d\n", entry->GetFileOffset()); + Interface::Print("File Size (Obsolete): %d\n", entry->GetFileSize()); Interface::Print("Partition Name: %s\n", entry->GetPartitionName()); - Interface::Print("Filename: %s\n", entry->GetFilename()); + Interface::Print("Flash Filename: %s\n", entry->GetFlashFilename()); + Interface::Print("FOTA Filename: %s\n", entry->GetFotaFilename()); } Interface::Print("\n"); } + +void Interface::SetStdoutErrors(bool enabled) +{ + stdoutErrors = enabled; +} |