diff --git a/README.md b/README.md index 14c551dd..ad85b7e1 100644 --- a/README.md +++ b/README.md @@ -68,6 +68,7 @@ Usage: `futurerestore [OPTIONS] iPSW` | ` -w ` | ` --wait ` | Keep rebooting until ApNonce matches APTicket (ApNonce collision, unreliable) | | ` -d ` | ` --debug ` | Show all code, use to save a log for debug testing | | ` -e ` | ` --exit-recovery ` | Exit recovery mode and quit | +| ` -c ` | ` --custom-latest VERSION ` | Specify custom latest version to use for SEP, Baseband and other FirmwareUpdater components | | | ` --use-pwndfu ` | Restoring devices with Odysseus method. Device needs to be in pwned DFU mode already | | | ` --no-ibss ` | Restoring devices with Odysseus method. For checkm8/iPwnder32 specifically, bootrom needs to be patched already with unless iPwnder. | | | ` --rdsk PATH ` | Set custom restore ramdisk for entering restoremode(requires use-pwndfu) | diff --git a/futurerestore/futurerestore.cpp b/futurerestore/futurerestore.cpp index 624d242b..f3408d06 100644 --- a/futurerestore/futurerestore.cpp +++ b/futurerestore/futurerestore.cpp @@ -114,6 +114,8 @@ futurerestore::futurerestore(bool isUpdateInstall, bool isPwnDfu, bool noIBSS, b nocache = 1; //tsschecker nocache _foundnonce = -1; + _useCustomLatest = false; + _customLatest = std::string(""); } bool futurerestore::init() { @@ -1421,6 +1423,22 @@ char *futurerestore::getLatestManifest() { if (--versionCnt == 0) reterror("[TSSC] automatic selection of firmware couldn't find for non-beta versions\n"); } + if(_useCustomLatest) { + i = 0; + while(i < versionCnt) { + versVals.version = strdup(versions[i++]); + std::string version(versVals.version); + if(!std::equal(_customLatest.begin(), _customLatest.end(), version.begin())) { + free((char *) versVals.version); + } else { + i = -1; + break; + } + } + if(i != -1) { + reterror("[TSSC] failed to find custom version for device!\n"); + } + } info("[TSSC] selecting latest firmware version: %s\n", versVals.version); if (bpos) *bpos = '\0'; if (versions) free(versions[versionCnt - 1]), free(versions); diff --git a/futurerestore/futurerestore.hpp b/futurerestore/futurerestore.hpp index c00d3a86..9e7cd515 100644 --- a/futurerestore/futurerestore.hpp +++ b/futurerestore/futurerestore.hpp @@ -68,7 +68,9 @@ class futurerestore { jssytok_t *_firmwareTokens = nullptr;; char *_latestManifest = nullptr; char *_latestFirmwareUrl = nullptr; - + bool _useCustomLatest = false; + std::string _customLatest; + plist_t _sepbuildmanifest = nullptr; plist_t _basebandbuildmanifest = nullptr; @@ -132,6 +134,7 @@ public: void loadSep(std::string sepPath); void loadBaseband(std::string basebandPath); + void setCustomLatest(std::string version){_customLatest = version; _useCustomLatest = true;} void setSepPath(std::string sepPath) {_sepPath = sepPath;} void setSepManifestPath(std::string sepManifestPath) {_sepManifestPath = sepManifestPath;} void setRamdiskPath(std::string ramdiskPath) {_ramdiskPath = ramdiskPath;} diff --git a/futurerestore/main.cpp b/futurerestore/main.cpp index a222c91f..d4cb8645 100644 --- a/futurerestore/main.cpp +++ b/futurerestore/main.cpp @@ -39,6 +39,7 @@ static struct option longopts[] = { { "update", no_argument, nullptr, 'u' }, { "debug", no_argument, nullptr, 'd' }, { "exit-recovery", no_argument, nullptr, 'e' }, + { "custom-latest", required_argument, nullptr, 'c' }, { "latest-sep", no_argument, nullptr, '0' }, { "no-restore", no_argument, nullptr, 'z' }, { "latest-baseband", no_argument, nullptr, '1' }, @@ -52,7 +53,7 @@ static struct option longopts[] = { { "serial", no_argument, nullptr, '8' }, { "boot-args", required_argument, nullptr, '9' }, { "no-cache", no_argument, nullptr, 'a' }, - { "skip-blob", no_argument, nullptr, 'c' }, + { "skip-blob", no_argument, nullptr, 'f' }, #endif { nullptr, 0, nullptr, 0 } }; @@ -83,6 +84,7 @@ void cmd_help(){ printf(" -d, --debug\t\t\tShow all code, use to save a log for debug testing\n"); printf(" -e, --exit-recovery\t\tExit recovery mode and quit\n"); printf(" -z, --no-restore\t\tDo not restore and end right before NOR data is sent\n"); + printf(" -c, --custom-latest VERSION\tSpecify custom latest version to use for SEP, Baseband and other FirmwareUpdater components\n"); #ifdef HAVE_LIBIPATCHER printf("\nOptions for downgrading with Odysseus:\n"); @@ -142,6 +144,7 @@ int main_r(int argc, const char * argv[]) { const char *sepPath = nullptr; const char *sepManifestPath = nullptr; const char *bootargs = nullptr; + std::string customLatest; const char *ramdiskPath = nullptr; const char *kernelPath = nullptr; const char *custom_nonce = nullptr; @@ -156,7 +159,7 @@ int main_r(int argc, const char * argv[]) { return -1; } - while ((opt = getopt_long(argc, (char* const *)argv, "ht:b:p:s:m:wudez0123456789ac", longopts, &optindex)) > 0) { + while ((opt = getopt_long(argc, (char* const *)argv, "ht:b:p:s:m:c:wude0z123456789af", longopts, &optindex)) > 0) { switch (opt) { case 't': // long option: "apticket"; can be called as short option apticketPaths.push_back(optarg); @@ -179,6 +182,9 @@ int main_r(int argc, const char * argv[]) { case 'u': // long option: "update"; can be called as short option flags |= FLAG_UPDATE; break; + case 'c': // long option: "custom-latest"; + customLatest = (optarg) ? std::string(optarg) : std::string(""); + break; case '0': // long option: "latest-sep"; flags |= FLAG_LATEST_SEP; break; @@ -223,7 +229,7 @@ int main_r(int argc, const char * argv[]) { case 'a': // long option: "no-cache"; flags |= FLAG_NO_CACHE; break; - case 'c': // long option: "skip-blob"; + case 'f': // long option: "skip-blob"; flags |= FLAG_SKIP_BLOB; break; #endif @@ -298,6 +304,10 @@ int main_r(int argc, const char * argv[]) { client.loadAPTickets(apticketPaths); } + if(!customLatest.empty()) { + client.setCustomLatest(customLatest); + } + if (!( ((!apticketPaths.empty() && ipsw) && ((basebandPath && basebandManifestPath) || ((flags & FLAG_LATEST_BASEBAND) || (flags & FLAG_NO_BASEBAND)))