diff --git a/README.md b/README.md index c1760e61..24abdb62 100644 --- a/README.md +++ b/README.md @@ -74,6 +74,8 @@ Usage: `futurerestore [OPTIONS] iPSW` | | ` --rkrn PATH ` | Set custom restore kernelcache for entering restoremode(requires use-pwndfu) | | | ` --set-nonce ` | Set custom nonce from your blob then exit recovery(requires use-pwndfu) | | | ` --set-nonce=0xNONCE ` | Set custom nonce then exit recovery(requires use-pwndfu) | +| | ` --serial ` | Enable serial during boot(requires serial cable and use-pwndfu) | +| | ` --boot-args "BOOTARGS" ` | Set custom restore boot-args(PROCEED WITH CAUTION)(requires use-pwndfu) | | | ` --latest-sep ` | Use latest signed SEP instead of manually specifying one | | ` -s ` | ` --sep PATH ` | Manually specify SEP to be flashed | | ` -m ` | ` --sep-manifest PATH ` | BuildManifest for requesting SEP ticket | diff --git a/futurerestore/futurerestore.cpp b/futurerestore/futurerestore.cpp index a729486f..3a3e5da1 100644 --- a/futurerestore/futurerestore.cpp +++ b/futurerestore/futurerestore.cpp @@ -106,7 +106,7 @@ extern "C"{ } #pragma mark futurerestore -futurerestore::futurerestore(bool isUpdateInstall, bool isPwnDfu, bool noIBSS, bool cfwRamdisk, bool cfwKernel, bool setNonce, bool noRestore) : _isUpdateInstall(isUpdateInstall), _isPwnDfu(isPwnDfu), _noIBSS(noIBSS), _cfwRamdisk(cfwRamdisk), _cfwKernel(cfwKernel), _setNonce(setNonce), _noRestore(noRestore){ +futurerestore::futurerestore(bool isUpdateInstall, bool isPwnDfu, bool noIBSS, bool setNonce, bool serial, bool noRestore) : _isUpdateInstall(isUpdateInstall), _isPwnDfu(isPwnDfu), _noIBSS(noIBSS), _setNonce(setNonce), _serial(serial), _noRestore(noRestore){ _client = idevicerestore_client_new(); if (_client == NULL) throw std::string("could not create idevicerestore client\n"); @@ -462,14 +462,24 @@ pair, size_t> getIPSWComponent(struct idevicerestore_client_t* return {(char*)component_data,component_size}; } -void futurerestore::enterPwnRecovery(plist_t build_identity, string bootargs){ +void futurerestore::enterPwnRecovery(plist_t build_identity, std::string bootargs){ #ifndef HAVE_LIBIPATCHER reterror("compiled without libipatcher"); #else - bootargs = "rd=md0 -restore -progress nand-enable-reformat=0x1 -v serial=0x3 debug=0x14e keepsyms=0x1 amfi=0xff amfi_unrestrict_task_for_pid=0x0 amfi_allow_any_signature=0x1 amfi_get_out_of_my_way=0x1 cs_enforcement_disable=0x1"; idevicerestore_mode_t *mode = 0; libipatcher::fw_key iBSSKeys; libipatcher::fw_key iBECKeys; + pair, size_t> iBSS; + pair, size_t> iBEC; + FILE *ibss = NULL; + FILE *ibec = NULL; + int rv; + bool cache1 = false; + bool cache2 = false; + std::string img3_end = ".patched.img3"; + std::string img4_end = ".patched.img4"; + std::string ibss_name = FUTURERESTORE_TMP_PATH"/ibss."; + std::string ibec_name = FUTURERESTORE_TMP_PATH"/ibec."; /* Assure device is in dfu */ irecv_device_event_subscribe(&_client->irecv_e_ctx, irecv_event_cb, _client); @@ -483,6 +493,43 @@ void futurerestore::enterPwnRecovery(plist_t build_identity, string bootargs){ mutex_unlock(&_client->device_event_mutex); info("Device found in DFU Mode.\n"); + ibss_name.append(getDeviceBoardNoCopy()); + ibec_name.append(getDeviceBoardNoCopy()); + ibss_name.append("."); + ibec_name.append("."); + ibss_name.append(_client->build); + ibec_name.append(_client->build); + if(_client->image4supported) { + ibss_name.append(img4_end); + ibec_name.append(img4_end); + } else { + ibss_name.append(img3_end); + ibec_name.append(img3_end); + } + + ibss = fopen(ibss_name.c_str(), "rb"); + if(ibss) { + fseek(ibss, 0, SEEK_END); + iBSS.second = ftell(ibss); + fseek(ibss, 0, SEEK_SET); + retassure(iBSS.first = (char*)malloc(iBSS.second), "failed to malloc memory for Rose\n"); + size_t freadRet=0; + retassure((freadRet = fread((char*)iBSS.first, 1, iBSS.second, ibss)) == iBSS.second, "failed to load iBSS. size=%zu but fread returned %zu\n",iBSS.second,freadRet); + fclose(ibss); + cache1 = true; + } + ibec = fopen(ibec_name.c_str(), "rb"); + if(ibec) { + fseek(ibec, 0, SEEK_END); + iBEC.second = ftell(ibec); + fseek(ibec, 0, SEEK_SET); + retassure(iBEC.first = (char*)malloc(iBEC.second), "failed to malloc memory for Rose\n"); + size_t freadRet=0; + retassure((freadRet = fread((char*)iBEC.first, 1, iBEC.second, ibec)) == iBEC.second, "failed to load iBEC. size=%zu but fread returned %zu\n",iBEC.second,freadRet); + fclose(ibec); + cache2 = true; + } + /* Patch bootloaders */ try { std::string board = getDeviceBoardNoCopy(); @@ -498,48 +545,52 @@ void futurerestore::enterPwnRecovery(plist_t build_identity, string bootargs){ reterror("getting keys failed with error: %d (%s). Are keys publicly available?",e.code(),e.what()); } - info("Patching iBSS\n"); - auto iBSS = getIPSWComponent(_client, build_identity, "iBSS"); - iBSS = move(libipatcher::patchiBSS((char*)iBSS.first, iBSS.second, iBSSKeys)); - - info("Patching iBEC\n"); - auto iBEC = getIPSWComponent(_client, build_identity, "iBEC"); - iBEC = move(libipatcher::patchiBEC((char*)iBEC.first, iBEC.second, iBECKeys, bootargs)); + if(!iBSS.first){ + info("Patching iBSS\n"); + iBSS = getIPSWComponent(_client, build_identity, "iBSS"); + iBSS = move(libipatcher::patchiBSS((char*)iBSS.first, iBSS.second, iBSSKeys)); + } + if(!iBEC.first) { + info("Patching iBEC\n"); + iBEC = getIPSWComponent(_client, build_identity, "iBEC"); + iBEC = move(libipatcher::patchiBEC((char*)iBEC.first, iBEC.second, iBECKeys, bootargs)); + } if (_client->image4supported) { /* if this is 64-bit, we need to back IM4P to IMG4 also due to the nature of iBoot64Patchers sigpatches we need to stich a valid signed im4m to it (but nonce is ignored) */ info("Repacking patched bootloaders as IMG4\n"); - iBSS = move(libipatcher::packIM4PToIMG4(iBSS.first, iBSS.second, _im4ms[0].first, _im4ms[0].second)); - iBEC = move(libipatcher::packIM4PToIMG4(iBEC.first, iBEC.second, _im4ms[0].first, _im4ms[0].second)); + if(!cache1) + iBSS = move(libipatcher::packIM4PToIMG4(iBSS.first, iBSS.second, _im4ms[0].first, _im4ms[0].second)); + if(!cache2) + iBEC = move(libipatcher::packIM4PToIMG4(iBEC.first, iBEC.second, _im4ms[0].first, _im4ms[0].second)); } - FILE *ibss = NULL; - FILE *ibec = NULL; - int rv; - retassure(ibss = fopen(FUTURERESTORE_TMP_PATH"/ibss.patched.img4", "wb"), "can't save patched ibss at %s\n", FUTURERESTORE_TMP_PATH"/ibss.patched.img4"); - retassure(rv = fwrite(iBSS.first, iBSS.second, 1, ibss), "can't save patched ibss at %s\n", FUTURERESTORE_TMP_PATH"/ibss.patched.img4"); - retassure(ibec = fopen(FUTURERESTORE_TMP_PATH"/ibec.patched.img4", "wb"), "can't save patched ibec at %s\n", FUTURERESTORE_TMP_PATH"/ibec.patched.img4"); - retassure(rv = fwrite(iBEC.first, iBEC.second, 1, ibec), "can't save patched ibec at %s\n", FUTURERESTORE_TMP_PATH"/ibec.patched.img4"); + retassure(ibss = fopen(ibss_name.c_str(), "wb"), "can't save patched ibss at %s\n", ibss_name.c_str()); + retassure(rv = fwrite(iBSS.first, iBSS.second, 1, ibss), "can't save patched ibss at %s\n", ibss_name.c_str()); + retassure(ibec = fopen(ibec_name.c_str(), "wb"), "can't save patched ibec at %s\n", ibec_name.c_str()); + retassure(rv = fwrite(iBEC.first, iBEC.second, 1, ibec), "can't save patched ibec at %s\n", ibec_name.c_str()); fflush(ibss); fclose(ibss); fflush(ibec); fclose(ibec); /* Send and boot bootloaders */ + irecv_error_t err = IRECV_E_UNKNOWN_ERROR; + if(!_noIBSS) { + /* send iBSS */ + info("Sending %s (%lu bytes)...\n", "iBSS", iBSS.second); + mutex_lock(&_client->device_event_mutex); + err = irecv_send_buffer(_client->dfu->client, (unsigned char *) (char *) iBSS.first, + (unsigned long) iBSS.second, 1); + retassure(err == IRECV_E_SUCCESS, "ERROR: Unable to send %s component: %s\n", "iBSS", irecv_strerror(err)); - // if(_noIBSS) goto label; - - /* send iBSS */ - info("Sending %s (%lu bytes)...\n", "iBSS", iBSS.second); - mutex_lock(&_client->device_event_mutex); - irecv_error_t err = irecv_send_buffer(_client->dfu->client, (unsigned char*)(char*)iBSS.first, (unsigned long)iBSS.second, 1); - retassure(err == IRECV_E_SUCCESS,"ERROR: Unable to send %s component: %s\n", "iBSS", irecv_strerror(err)); - - info("Booting iBSS, waiting for device to disconnect...\n"); - cond_wait_timeout(&_client->device_event_cond, &_client->device_event_mutex, 10000); + info("Booting iBSS, waiting for device to disconnect...\n"); + cond_wait_timeout(&_client->device_event_cond, &_client->device_event_mutex, 10000); + retassure(((_client->mode == MODE_UNKNOWN) || (mutex_unlock(&_client->device_event_mutex),0)), "Device did not disconnect. Possibly invalid iBSS. Reset device and try again"); info("Booting iBSS, waiting for device to reconnect...\n"); + } bool dfu = false; if((_client->device->chip_id >= 0x7000 && _client->device->chip_id <= 0x8004) || (_client->device->chip_id >= 0x8900 && _client->device->chip_id <= 0x8965)) { cond_wait_timeout(&_client->device_event_cond, &_client->device_event_mutex, 10000); @@ -564,7 +615,6 @@ void futurerestore::enterPwnRecovery(plist_t build_identity, string bootargs){ mutex_unlock(&_client->device_event_mutex); getDeviceMode(true); retassure(((recovery_client_new(_client) == IRECV_E_SUCCESS) || (mutex_unlock(&_client->device_event_mutex),0)), "Failed to connect to device in Recovery Mode!"); - mutex_lock(&_client->device_event_mutex); } } else if((_client->device->chip_id >= 0x8006 && _client->device->chip_id <= 0x8030) || (_client->device->chip_id >= 0x8101 && _client->device->chip_id <= 0x8301)) { dfu = true; @@ -1347,7 +1397,16 @@ void futurerestore::doRestore(const char *ipsw){ retassure((getDeviceMode(true) == _MODE_DFU) || (getDeviceMode(false) == _MODE_RECOVERY && _noIBSS), "unexpected device mode\n"); irecv_device_event_unsubscribe(client->irecv_e_ctx); client->idevice_e_ctx = NULL; - enterPwnRecovery(build_identity); + std::string bootargs = ""; + if(_boot_args != NULL) { + bootargs = _boot_args; + } else { + if (_serial) { + bootargs.append("serial=0x3 "); + } + bootargs.append("rd=md0 -restore -progress nand-enable-reformat=0x1 -v debug=0x14e keepsyms=0x1 amfi=0xff amfi_unrestrict_task_for_pid=0x0 amfi_allow_any_signature=0x1 amfi_get_out_of_my_way=0x1 cs_enforcement_disable=0x1"); + } + enterPwnRecovery(build_identity, bootargs); irecv_device_event_unsubscribe(_client->irecv_e_ctx); _client->idevice_e_ctx = NULL; irecv_device_event_subscribe(&client->irecv_e_ctx, irecv_event_cb, _client); diff --git a/futurerestore/futurerestore.hpp b/futurerestore/futurerestore.hpp index d87322ff..7ed9f616 100644 --- a/futurerestore/futurerestore.hpp +++ b/futurerestore/futurerestore.hpp @@ -58,9 +58,8 @@ class futurerestore { bool _isUpdateInstall = false; bool _isPwnDfu = false; bool _noIBSS = false; - bool _cfwRamdisk = false; - bool _cfwKernel = false; bool _setNonce = false; + bool _serial = false; bool _noRestore = false; char *_firmwareJson = NULL; @@ -84,15 +83,16 @@ class futurerestore { const char *_kernelPath = NULL; const char *_custom_nonce = NULL; + const char *_boot_args = NULL; bool _enterPwnRecoveryRequested = false; bool _rerestoreiOS9 = false; //methods - void enterPwnRecovery(plist_t build_identity, std::string bootargs = ""); + void enterPwnRecovery(plist_t build_identity, std::string bootargs); void enterPwnRecovery2(plist_t build_identity, std::string bootargs = ""); public: - futurerestore(bool isUpdateInstall = false, bool isPwnDfu = false, bool noIBSS = false, bool cfwRamdisk = false, bool cfwKernel = false, bool setNonce = false, bool noRestore = false); + futurerestore(bool isUpdateInstall = false, bool isPwnDfu = false, bool noIBSS = false, bool setNonce = false, bool serial = false, bool noRestore = false); bool init(); int getDeviceMode(bool reRequest); uint64_t getDeviceEcid(); @@ -133,6 +133,7 @@ public: void setRamdiskPath(const char *ramdiskPath); void setKernelPath(const char *kernelPath); void setNonce(const char *custom_nonce){_custom_nonce = custom_nonce;}; + void setBootArgs(const char *boot_args){_boot_args = boot_args;}; bool isUpdateInstall(){return _isUpdateInstall;}; plist_t sepManifest(){return _sepbuildmanifest;}; diff --git a/futurerestore/main.cpp b/futurerestore/main.cpp index f07ec5a7..ec760c20 100644 --- a/futurerestore/main.cpp +++ b/futurerestore/main.cpp @@ -34,27 +34,29 @@ extern "C"{ #endif static struct option longopts[] = { - { "apticket", required_argument, NULL, 't' }, - { "baseband", required_argument, NULL, 'b' }, - { "baseband-manifest", required_argument, NULL, 'p' }, - { "sep", required_argument, NULL, 's' }, - { "sep-manifest", required_argument, NULL, 'm' }, - { "wait", no_argument, NULL, 'w' }, - { "update", no_argument, NULL, 'u' }, - { "debug", no_argument, NULL, 'd' }, - { "exit-recovery", no_argument, NULL, 'e' }, - { "latest-sep", no_argument, NULL, '0' }, - { "no-restore", no_argument, NULL, 'z' }, - { "latest-baseband", no_argument, NULL, '1' }, - { "no-baseband", no_argument, NULL, '2' }, + { "apticket", required_argument, NULL, 't' }, + { "baseband", required_argument, NULL, 'b' }, + { "baseband-manifest", required_argument, NULL, 'p' }, + { "sep", required_argument, NULL, 's' }, + { "sep-manifest", required_argument, NULL, 'm' }, + { "wait", no_argument, NULL, 'w' }, + { "update", no_argument, NULL, 'u' }, + { "debug", no_argument, NULL, 'd' }, + { "exit-recovery", no_argument, NULL, 'e' }, + { "latest-sep", no_argument, NULL, '0' }, + { "no-restore", no_argument, NULL, 'z' }, + { "latest-baseband", no_argument, NULL, '1' }, + { "no-baseband", no_argument, NULL, '2' }, #ifdef HAVE_LIBIPATCHER - { "use-pwndfu", no_argument, NULL, '3' }, - { "no-ibss", no_argument, NULL, '4' }, - { "rdsk", required_argument, NULL, '5' }, - { "rkrn", required_argument, NULL, '6' }, - { "set-nonce", optional_argument, NULL, '7' }, + { "use-pwndfu", no_argument, NULL, '3' }, + { "no-ibss", no_argument, NULL, '4' }, + { "rdsk", required_argument, NULL, '5' }, + { "rkrn", required_argument, NULL, '6' }, + { "set-nonce", optional_argument, NULL, '7' }, + { "serial", no_argument, NULL, '8' }, + { "boot-args", required_argument, NULL, '9' }, #endif - { NULL, 0, NULL, 0 } + { NULL, 0, NULL, 0 } }; #define FLAG_WAIT 1 << 0 @@ -67,7 +69,9 @@ static struct option longopts[] = { #define FLAG_RESTORE_RAMDISK 1 << 7 #define FLAG_RESTORE_KERNEL 1 << 8 #define FLAG_SET_NONCE 1 << 9 -#define FLAG_NO_RESTORE_FR 1 << 10 +#define FLAG_SERIAL 1 << 10 +#define FLAG_BOOT_ARGS 1 << 11 +#define FLAG_NO_RESTORE_FR 1 << 12 void cmd_help(){ printf("Usage: futurerestore [OPTIONS] iPSW\n"); printf("Allows restoring to non-matching firmware with custom SEP+baseband\n"); @@ -79,7 +83,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"); - + #ifdef HAVE_LIBIPATCHER printf("\nOptions for downgrading with Odysseus:\n"); printf(" --use-pwndfu\t\tRestoring devices with Odysseus method. Device needs to be in pwned DFU mode already\n"); @@ -88,13 +92,15 @@ void cmd_help(){ printf(" --rkrn PATH\t\tSet custom restore kernelcache for entering restoremode(requires use-pwndfu)\n"); printf(" --set-nonce\t\tSet custom nonce from your blob then exit recovery(requires use-pwndfu)\n"); printf(" --set-nonce=0xNONCE\tSet custom nonce then exit recovery(requires use-pwndfu)\n"); + printf(" --serial\t\t\tEnable serial during boot(requires serial cable and use-pwndfu)\n"); + printf(" --boot-args\t\tSet custom restore boot-args(PROCEED WITH CAUTION)(requires use-pwndfu)\n"); #endif - + printf("\nOptions for SEP:\n"); printf(" --latest-sep\t\tUse latest signed SEP instead of manually specifying one\n"); printf(" -s, --sep PATH\t\tSEP to be flashed\n"); printf(" -m, --sep-manifest PATH\tBuildManifest for requesting SEP ticket\n"); - + printf("\nOptions for baseband:\n"); printf(" --latest-baseband\t\tUse latest signed baseband instead of manually specifying one\n"); printf(" -b, --baseband PATH\t\tBaseband to be flashed\n"); @@ -128,10 +134,10 @@ int main_r(int argc, const char * argv[]) { long flags = 0; bool exitRecovery = false; bool noRestore = false; - + int isSepManifestSigned = 0; int isBasebandSigned = 0; - + const char *ipsw = NULL; const char *basebandPath = NULL; const char *basebandManifestPath = NULL; @@ -143,16 +149,16 @@ int main_r(int argc, const char * argv[]) { const char *custom_nonce = NULL; vector apticketPaths; - + t_devicevals devVals = {0}; t_iosVersion versVals = {0}; - + if (argc == 1){ cmd_help(); return -1; } - while ((opt = getopt_long(argc, (char* const *)argv, "ht:b:p:s:m:wudez01234567", longopts, &optindex)) > 0) { + while ((opt = getopt_long(argc, (char* const *)argv, "ht:b:p:s:m:wudez0123456789", longopts, &optindex)) > 0) { switch (opt) { case 't': // long option: "apticket"; can be called as short option apticketPaths.push_back(optarg); @@ -209,6 +215,13 @@ int main_r(int argc, const char * argv[]) { retassure(gen, "failed to parse generator. Make sure it is in format 0x%16llx"); } break; + case '8': // long option: "serial"; + flags |= FLAG_SERIAL; + break; + case '9': // long option: "boot-args"; + flags |= FLAG_BOOT_ARGS; + bootargs = (optarg) ? optarg : NULL; + break; #endif case 'e': // long option: "exit-recovery"; can be called as short option exitRecovery = true; @@ -224,11 +237,11 @@ int main_r(int argc, const char * argv[]) { return -1; } } - + if (argc-optind == 1) { argc -= optind; argv += optind; - + ipsw = argv[0]; }else if (argc == optind && flags & FLAG_WAIT) { info("User requested to only wait for ApNonce to match, but not for actually restoring\n"); @@ -243,12 +256,11 @@ int main_r(int argc, const char * argv[]) { } return -5; } - - futurerestore client(flags & FLAG_UPDATE, flags & FLAG_IS_PWN_DFU, flags & FLAG_NO_IBSS, flags & FLAG_RESTORE_RAMDISK, flags & FLAG_RESTORE_KERNEL, flags & FLAG_SET_NONCE, flags & FLAG_NO_RESTORE_FR); + + futurerestore client(flags & FLAG_UPDATE, flags & FLAG_IS_PWN_DFU, flags & FLAG_NO_IBSS, flags & FLAG_SET_NONCE, flags & FLAG_SERIAL, flags & FLAG_NO_RESTORE_FR); retassure(client.init(),"can't init, no device found\n"); - + printf("futurerestore init done\n"); - retassure(!bootargs || (flags & FLAG_IS_PWN_DFU),"--just-boot requires --use-pwndfu\n"); if(flags & FLAG_NO_IBSS) retassure((flags & FLAG_IS_PWN_DFU),"--no-ibss requires --use-pwndfu\n"); if(flags & FLAG_RESTORE_RAMDISK) @@ -257,25 +269,33 @@ int main_r(int argc, const char * argv[]) { retassure((flags & FLAG_IS_PWN_DFU),"--rkrn requires --use-pwndfu\n"); if(flags & FLAG_SET_NONCE) retassure((flags & FLAG_IS_PWN_DFU),"--set-nonce requires --use-pwndfu\n"); + if(flags & FLAG_SET_NONCE && client.is32bit()) + error("--set-nonce not supported on 32bit devices.\n"); if(flags & FLAG_RESTORE_RAMDISK) retassure((flags & FLAG_RESTORE_KERNEL),"--rdsk requires --rkrn\n"); + if(flags & FLAG_SERIAL) { + retassure((flags & FLAG_IS_PWN_DFU),"--serial requires --use-pwndfu\n"); + retassure(!(flags & FLAG_BOOT_ARGS),"--serial conflicts with --boot-args\n"); + } + if(flags & FLAG_BOOT_ARGS) + retassure((flags & FLAG_IS_PWN_DFU),"--boot-args requires --use-pwndfu\n"); if (exitRecovery) { client.exitRecovery(); info("Done\n"); return 0; } - + try { if (apticketPaths.size()) client.loadAPTickets(apticketPaths); - + if (!( - ((apticketPaths.size() && ipsw) - && ((basebandPath && basebandManifestPath) || ((flags & FLAG_LATEST_BASEBAND) || (flags & FLAG_NO_BASEBAND))) - && ((sepPath && sepManifestPath) || (flags & FLAG_LATEST_SEP) || client.is32bit()) - ) || (ipsw && bootargs && (flags & FLAG_IS_PWN_DFU)) - )) { - + ((apticketPaths.size() && ipsw) + && ((basebandPath && basebandManifestPath) || ((flags & FLAG_LATEST_BASEBAND) || (flags & FLAG_NO_BASEBAND))) + && ((sepPath && sepManifestPath) || (flags & FLAG_LATEST_SEP) || client.is32bit()) + ) || (ipsw && (flags & FLAG_IS_PWN_DFU)) + )) { + if (!(flags & FLAG_WAIT) || ipsw){ error("missing argument\n"); cmd_help(); @@ -287,68 +307,70 @@ int main_r(int argc, const char * argv[]) { } goto error; } - if (bootargs){ - + + devVals.deviceModel = (char*)client.getDeviceModelNoCopy(); + devVals.deviceBoard = (char*)client.getDeviceBoardNoCopy(); + + if(flags & FLAG_RESTORE_RAMDISK) { + client.setRamdiskPath(ramdiskPath); + client.loadRamdisk(ramdiskPath); + } + + if(flags & FLAG_RESTORE_KERNEL) { + client.setKernelPath(kernelPath); + client.loadKernel(kernelPath); + } + + if(flags & FLAG_SET_NONCE) { + client.setNonce(custom_nonce); + } + + if(flags & FLAG_BOOT_ARGS) { + client.setBootArgs(bootargs); + } + + if (flags & FLAG_LATEST_SEP){ + info("user specified to use latest signed SEP\n"); + client.loadLatestSep(); + }else if (!client.is32bit()){ + client.loadSep(sepPath); + client.setSepManifestPath(sepManifestPath); + } + + versVals.basebandMode = kBasebandModeWithoutBaseband; + if (!client.is32bit() && !(isSepManifestSigned = isManifestSignedForDevice(client.sepManifestPath(), &devVals, &versVals, NULL))){ + reterror("SEP firmware is NOT being signed!\n"); + } + if (flags & FLAG_NO_BASEBAND){ + printf("\nWARNING: user specified is not to flash a baseband. This can make the restore fail if the device needs a baseband!\n"); + printf("if you added this flag by mistake, you can press CTRL-C now to cancel\n"); + int c = 10; + printf("continuing restore in "); + while (c) { + printf("%d ",c--); + fflush(stdout); + sleep(1); + } + printf("\n"); }else{ - devVals.deviceModel = (char*)client.getDeviceModelNoCopy(); - devVals.deviceBoard = (char*)client.getDeviceBoardNoCopy(); - - if(flags & FLAG_SET_NONCE) { - client.setNonce(custom_nonce); - } - - if(flags & FLAG_RESTORE_RAMDISK) { - client.setRamdiskPath(ramdiskPath); - client.loadRamdisk(ramdiskPath); - } - - if(flags & FLAG_RESTORE_KERNEL) { - client.setKernelPath(kernelPath); - client.loadKernel(kernelPath); - } - - if (flags & FLAG_LATEST_SEP){ - info("user specified to use latest signed SEP\n"); - client.loadLatestSep(); - }else if (!client.is32bit()){ - client.loadSep(sepPath); - client.setSepManifestPath(sepManifestPath); - } - - versVals.basebandMode = kBasebandModeWithoutBaseband; - if (!client.is32bit() && !(isSepManifestSigned = isManifestSignedForDevice(client.sepManifestPath(), &devVals, &versVals, NULL))){ - reterror("SEP firmware is NOT being signed!\n"); - } - if (flags & FLAG_NO_BASEBAND){ - printf("\nWARNING: user specified is not to flash a baseband. This can make the restore fail if the device needs a baseband!\n"); - printf("if you added this flag by mistake, you can press CTRL-C now to cancel\n"); - int c = 10; - printf("continuing restore in "); - while (c) { - printf("%d ",c--); - fflush(stdout); - sleep(1); - } - printf("\n"); + if (flags & FLAG_LATEST_BASEBAND){ + info("user specified to use latest signed baseband\n"); + client.loadLatestBaseband(); }else{ - if (flags & FLAG_LATEST_BASEBAND){ - info("user specified to use latest signed baseband\n"); - client.loadLatestBaseband(); - }else{ - client.setBasebandPath(basebandPath); - client.setBasebandManifestPath(basebandManifestPath); - printf("Did set SEP+baseband path and firmware\n"); - } - - versVals.basebandMode = kBasebandModeOnlyBaseband; - if (!(devVals.bbgcid = client.getBasebandGoldCertIDFromDevice())){ - printf("[WARNING] using tsschecker's fallback to get BasebandGoldCertID. This might result in invalid baseband signing status information\n"); - } - if (!(isBasebandSigned = isManifestSignedForDevice(client.basebandManifestPath(), &devVals, &versVals, NULL))) { - reterror("baseband firmware is NOT being signed!\n"); - } + client.setBasebandPath(basebandPath); + client.setBasebandManifestPath(basebandManifestPath); + printf("Did set SEP+baseband path and firmware\n"); + } + + versVals.basebandMode = kBasebandModeOnlyBaseband; + if (!(devVals.bbgcid = client.getBasebandGoldCertIDFromDevice())){ + printf("[WARNING] using tsschecker's fallback to get BasebandGoldCertID. This might result in invalid baseband signing status information\n"); + } + if (!(isBasebandSigned = isManifestSignedForDevice(client.basebandManifestPath(), &devVals, &versVals, NULL))) { + reterror("baseband firmware is NOT being signed!\n"); } } + if(!client.is32bit()) client.downloadLatestFirmwareComponents(); client.putDeviceIntoRecovery(); @@ -360,7 +382,7 @@ int main_r(int argc, const char * argv[]) { printf("[Error] Fail code=%d\n",err); goto error; } - + try { client.doRestore(ipsw); printf("Done: restoring succeeded!\n"); @@ -368,8 +390,8 @@ int main_r(int argc, const char * argv[]) { e.dump(); printf("Done: restoring failed!\n"); } - -error: + + error: if (err){ printf("Failed with error code=%d\n",err); }