mirror of
				https://github.com/tihmstar/futurerestore.git
				synced 2025-11-03 18:14:55 +00:00 
			
		
		
		
	WIP updating idevicerestore
This commit is contained in:
		
							parent
							
								
									292fca0e02
								
							
						
					
					
						commit
						def6e7ba8f
					
				
							
								
								
									
										2
									
								
								external/idevicerestore
									
									
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
								
							
						
						
									
										2
									
								
								external/idevicerestore
									
									
									
									
										vendored
									
									
								
							| 
						 | 
					@ -1 +1 @@
 | 
				
			||||||
Subproject commit 5411b6bd9a2bbf85ec7ab4bef6bc7d168a5bf79b
 | 
					Subproject commit 81867167df74c07d83b6784f48be6ca4d70ed4a4
 | 
				
			||||||
| 
						 | 
					@ -25,7 +25,7 @@
 | 
				
			||||||
		8799B0B71D89DAFF002F4D5F /* normal.c in Sources */ = {isa = PBXBuildFile; fileRef = 8785876C1D89D1C1008689F0 /* normal.c */; };
 | 
							8799B0B71D89DAFF002F4D5F /* normal.c in Sources */ = {isa = PBXBuildFile; fileRef = 8785876C1D89D1C1008689F0 /* normal.c */; };
 | 
				
			||||||
		8799B0B81D89DAFF002F4D5F /* recovery.c in Sources */ = {isa = PBXBuildFile; fileRef = 8785876E1D89D1C1008689F0 /* recovery.c */; };
 | 
							8799B0B81D89DAFF002F4D5F /* recovery.c in Sources */ = {isa = PBXBuildFile; fileRef = 8785876E1D89D1C1008689F0 /* recovery.c */; };
 | 
				
			||||||
		8799B0B91D89DB0D002F4D5F /* img3.c in Sources */ = {isa = PBXBuildFile; fileRef = 8785875E1D89D1C1008689F0 /* img3.c */; };
 | 
							8799B0B91D89DB0D002F4D5F /* img3.c in Sources */ = {isa = PBXBuildFile; fileRef = 8785875E1D89D1C1008689F0 /* img3.c */; };
 | 
				
			||||||
		8799B0BB1D89DB12002F4D5F /* download.c in Sources */ = {isa = PBXBuildFile; fileRef = 878587551D89D1C1008689F0 /* download.c */; };
 | 
							8799B0BB1D89DB12002F4D5F /* download.c in Sources */ = {isa = PBXBuildFile; fileRef = 878587551D89D1C1008689F0 /* download.c */; settings = {COMPILER_FLAGS = "-DPACKAGE_VERSION=\"\""; }; };
 | 
				
			||||||
		8799B0BC1D89DB27002F4D5F /* ipsw.c in Sources */ = {isa = PBXBuildFile; fileRef = 878587621D89D1C1008689F0 /* ipsw.c */; };
 | 
							8799B0BC1D89DB27002F4D5F /* ipsw.c in Sources */ = {isa = PBXBuildFile; fileRef = 878587621D89D1C1008689F0 /* ipsw.c */; };
 | 
				
			||||||
		8799B0BD1D89DB27002F4D5F /* limera1n.c in Sources */ = {isa = PBXBuildFile; fileRef = 878587641D89D1C1008689F0 /* limera1n.c */; };
 | 
							8799B0BD1D89DB27002F4D5F /* limera1n.c in Sources */ = {isa = PBXBuildFile; fileRef = 878587641D89D1C1008689F0 /* limera1n.c */; };
 | 
				
			||||||
		8799B0BE1D89DB27002F4D5F /* restore.c in Sources */ = {isa = PBXBuildFile; fileRef = 878587701D89D1C1008689F0 /* restore.c */; };
 | 
							8799B0BE1D89DB27002F4D5F /* restore.c in Sources */ = {isa = PBXBuildFile; fileRef = 878587701D89D1C1008689F0 /* restore.c */; };
 | 
				
			||||||
| 
						 | 
					@ -39,6 +39,9 @@
 | 
				
			||||||
		8799B0CA1D89E371002F4D5F /* img4.c in Sources */ = {isa = PBXBuildFile; fileRef = 878587601D89D1C1008689F0 /* img4.c */; };
 | 
							8799B0CA1D89E371002F4D5F /* img4.c in Sources */ = {isa = PBXBuildFile; fileRef = 878587601D89D1C1008689F0 /* img4.c */; };
 | 
				
			||||||
		8799B0CB1D89F796002F4D5F /* tsschecker.c in Sources */ = {isa = PBXBuildFile; fileRef = 8785879F1D89D2BA008689F0 /* tsschecker.c */; };
 | 
							8799B0CB1D89F796002F4D5F /* tsschecker.c in Sources */ = {isa = PBXBuildFile; fileRef = 8785879F1D89D2BA008689F0 /* tsschecker.c */; };
 | 
				
			||||||
		8799B0CC1D89F7B9002F4D5F /* download.c in Sources */ = {isa = PBXBuildFile; fileRef = 878587981D89D2BA008689F0 /* download.c */; };
 | 
							8799B0CC1D89F7B9002F4D5F /* download.c in Sources */ = {isa = PBXBuildFile; fileRef = 878587981D89D2BA008689F0 /* download.c */; };
 | 
				
			||||||
 | 
							87B517C3236EF36B009EAB8F /* ftab.c in Sources */ = {isa = PBXBuildFile; fileRef = 87B517C1236EF36B009EAB8F /* ftab.c */; };
 | 
				
			||||||
 | 
							87B517C6236EF3B0009EAB8F /* json_plist.c in Sources */ = {isa = PBXBuildFile; fileRef = 87B517C5236EF3B0009EAB8F /* json_plist.c */; };
 | 
				
			||||||
 | 
							87B517C9236EF3CD009EAB8F /* jsmn.c in Sources */ = {isa = PBXBuildFile; fileRef = 87B517C7236EF3CD009EAB8F /* jsmn.c */; };
 | 
				
			||||||
		87F574CB1E151E97008D5C4D /* libfragmentzip.0.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 87F574CA1E151E97008D5C4D /* libfragmentzip.0.dylib */; };
 | 
							87F574CB1E151E97008D5C4D /* libfragmentzip.0.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 87F574CA1E151E97008D5C4D /* libfragmentzip.0.dylib */; };
 | 
				
			||||||
		87F574D01E151F44008D5C4D /* libcrypto.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 87F574C51E151D42008D5C4D /* libcrypto.dylib */; };
 | 
							87F574D01E151F44008D5C4D /* libcrypto.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 87F574C51E151D42008D5C4D /* libcrypto.dylib */; };
 | 
				
			||||||
/* End PBXBuildFile section */
 | 
					/* End PBXBuildFile section */
 | 
				
			||||||
| 
						 | 
					@ -129,6 +132,12 @@
 | 
				
			||||||
		878E1AC41F73EB3F00B1565B /* libzip.5.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libzip.5.dylib; path = ../../../../usr/local/Cellar/libzip/1.3.0/lib/libzip.5.dylib; sourceTree = "<group>"; };
 | 
							878E1AC41F73EB3F00B1565B /* libzip.5.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libzip.5.dylib; path = ../../../../usr/local/Cellar/libzip/1.3.0/lib/libzip.5.dylib; sourceTree = "<group>"; };
 | 
				
			||||||
		8799B0B01D89D99D002F4D5F /* futurerestore.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = futurerestore.cpp; sourceTree = "<group>"; };
 | 
							8799B0B01D89D99D002F4D5F /* futurerestore.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = futurerestore.cpp; sourceTree = "<group>"; };
 | 
				
			||||||
		8799B0B11D89D99D002F4D5F /* futurerestore.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = futurerestore.hpp; sourceTree = "<group>"; };
 | 
							8799B0B11D89D99D002F4D5F /* futurerestore.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = futurerestore.hpp; sourceTree = "<group>"; };
 | 
				
			||||||
 | 
							87B517C1236EF36B009EAB8F /* ftab.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ftab.c; sourceTree = "<group>"; };
 | 
				
			||||||
 | 
							87B517C2236EF36B009EAB8F /* ftab.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ftab.h; sourceTree = "<group>"; };
 | 
				
			||||||
 | 
							87B517C4236EF3B0009EAB8F /* json_plist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = json_plist.h; sourceTree = "<group>"; };
 | 
				
			||||||
 | 
							87B517C5236EF3B0009EAB8F /* json_plist.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = json_plist.c; sourceTree = "<group>"; };
 | 
				
			||||||
 | 
							87B517C7236EF3CD009EAB8F /* jsmn.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jsmn.c; sourceTree = "<group>"; };
 | 
				
			||||||
 | 
							87B517C8236EF3CD009EAB8F /* jsmn.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = jsmn.h; sourceTree = "<group>"; };
 | 
				
			||||||
		87F574C51E151D42008D5C4D /* libcrypto.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libcrypto.dylib; path = ../../../../usr/lib/libcrypto.dylib; sourceTree = "<group>"; };
 | 
							87F574C51E151D42008D5C4D /* libcrypto.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libcrypto.dylib; path = ../../../../usr/lib/libcrypto.dylib; sourceTree = "<group>"; };
 | 
				
			||||||
		87F574C71E151DA6008D5C4D /* libcommonCrypto.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libcommonCrypto.tbd; path = usr/lib/system/libcommonCrypto.tbd; sourceTree = SDKROOT; };
 | 
							87F574C71E151DA6008D5C4D /* libcommonCrypto.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libcommonCrypto.tbd; path = usr/lib/system/libcommonCrypto.tbd; sourceTree = SDKROOT; };
 | 
				
			||||||
		87F574CA1E151E97008D5C4D /* libfragmentzip.0.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libfragmentzip.0.dylib; path = ../../../../usr/local/lib/libfragmentzip.0.dylib; sourceTree = "<group>"; };
 | 
							87F574CA1E151E97008D5C4D /* libfragmentzip.0.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libfragmentzip.0.dylib; path = ../../../../usr/local/lib/libfragmentzip.0.dylib; sourceTree = "<group>"; };
 | 
				
			||||||
| 
						 | 
					@ -224,6 +233,12 @@
 | 
				
			||||||
				8785875F1D89D1C1008689F0 /* img3.h */,
 | 
									8785875F1D89D1C1008689F0 /* img3.h */,
 | 
				
			||||||
				878587601D89D1C1008689F0 /* img4.c */,
 | 
									878587601D89D1C1008689F0 /* img4.c */,
 | 
				
			||||||
				878587611D89D1C1008689F0 /* img4.h */,
 | 
									878587611D89D1C1008689F0 /* img4.h */,
 | 
				
			||||||
 | 
									87B517C5236EF3B0009EAB8F /* json_plist.c */,
 | 
				
			||||||
 | 
									87B517C4236EF3B0009EAB8F /* json_plist.h */,
 | 
				
			||||||
 | 
									87B517C1236EF36B009EAB8F /* ftab.c */,
 | 
				
			||||||
 | 
									87B517C2236EF36B009EAB8F /* ftab.h */,
 | 
				
			||||||
 | 
									87B517C7236EF3CD009EAB8F /* jsmn.c */,
 | 
				
			||||||
 | 
									87B517C8236EF3CD009EAB8F /* jsmn.h */,
 | 
				
			||||||
				878587621D89D1C1008689F0 /* ipsw.c */,
 | 
									878587621D89D1C1008689F0 /* ipsw.c */,
 | 
				
			||||||
				878587631D89D1C1008689F0 /* ipsw.h */,
 | 
									878587631D89D1C1008689F0 /* ipsw.h */,
 | 
				
			||||||
				878587641D89D1C1008689F0 /* limera1n.c */,
 | 
									878587641D89D1C1008689F0 /* limera1n.c */,
 | 
				
			||||||
| 
						 | 
					@ -342,6 +357,7 @@
 | 
				
			||||||
				8799B0B41D89DAF6002F4D5F /* tss.c in Sources */,
 | 
									8799B0B41D89DAF6002F4D5F /* tss.c in Sources */,
 | 
				
			||||||
				8799B0C01D89DB38002F4D5F /* fdr.c in Sources */,
 | 
									8799B0C01D89DB38002F4D5F /* fdr.c in Sources */,
 | 
				
			||||||
				8799B0BC1D89DB27002F4D5F /* ipsw.c in Sources */,
 | 
									8799B0BC1D89DB27002F4D5F /* ipsw.c in Sources */,
 | 
				
			||||||
 | 
									87B517C3236EF36B009EAB8F /* ftab.c in Sources */,
 | 
				
			||||||
				8799B0CC1D89F7B9002F4D5F /* download.c in Sources */,
 | 
									8799B0CC1D89F7B9002F4D5F /* download.c in Sources */,
 | 
				
			||||||
				8799B0B91D89DB0D002F4D5F /* img3.c in Sources */,
 | 
									8799B0B91D89DB0D002F4D5F /* img3.c in Sources */,
 | 
				
			||||||
				8799B0B51D89DAFF002F4D5F /* common.c in Sources */,
 | 
									8799B0B51D89DAFF002F4D5F /* common.c in Sources */,
 | 
				
			||||||
| 
						 | 
					@ -350,12 +366,14 @@
 | 
				
			||||||
				8799B0B31D89DAE7002F4D5F /* idevicerestore.c in Sources */,
 | 
									8799B0B31D89DAE7002F4D5F /* idevicerestore.c in Sources */,
 | 
				
			||||||
				8799B0BB1D89DB12002F4D5F /* download.c in Sources */,
 | 
									8799B0BB1D89DB12002F4D5F /* download.c in Sources */,
 | 
				
			||||||
				8799B0B71D89DAFF002F4D5F /* normal.c in Sources */,
 | 
									8799B0B71D89DAFF002F4D5F /* normal.c in Sources */,
 | 
				
			||||||
 | 
									87B517C9236EF3CD009EAB8F /* jsmn.c in Sources */,
 | 
				
			||||||
				8799B0C31D89DB4B002F4D5F /* socket.c in Sources */,
 | 
									8799B0C31D89DB4B002F4D5F /* socket.c in Sources */,
 | 
				
			||||||
				8799B0C21D89DB46002F4D5F /* thread.c in Sources */,
 | 
									8799B0C21D89DB46002F4D5F /* thread.c in Sources */,
 | 
				
			||||||
				8799B0B61D89DAFF002F4D5F /* dfu.c in Sources */,
 | 
									8799B0B61D89DAFF002F4D5F /* dfu.c in Sources */,
 | 
				
			||||||
				8799B0BD1D89DB27002F4D5F /* limera1n.c in Sources */,
 | 
									8799B0BD1D89DB27002F4D5F /* limera1n.c in Sources */,
 | 
				
			||||||
				8799B0C51D89DB67002F4D5F /* locking.c in Sources */,
 | 
									8799B0C51D89DB67002F4D5F /* locking.c in Sources */,
 | 
				
			||||||
				878587471D89CFDC008689F0 /* main.cpp in Sources */,
 | 
									878587471D89CFDC008689F0 /* main.cpp in Sources */,
 | 
				
			||||||
 | 
									87B517C6236EF3B0009EAB8F /* json_plist.c in Sources */,
 | 
				
			||||||
				8799B0BF1D89DB38002F4D5F /* asr.c in Sources */,
 | 
									8799B0BF1D89DB38002F4D5F /* asr.c in Sources */,
 | 
				
			||||||
				8799B0BE1D89DB27002F4D5F /* restore.c in Sources */,
 | 
									8799B0BE1D89DB27002F4D5F /* restore.c in Sources */,
 | 
				
			||||||
				8799B0CB1D89F796002F4D5F /* tsschecker.c in Sources */,
 | 
									8799B0CB1D89F796002F4D5F /* tsschecker.c in Sources */,
 | 
				
			||||||
| 
						 | 
					@ -457,6 +475,7 @@
 | 
				
			||||||
					"$(inherited)",
 | 
										"$(inherited)",
 | 
				
			||||||
					"IDEVICERESTORE_NOMAIN=1",
 | 
										"IDEVICERESTORE_NOMAIN=1",
 | 
				
			||||||
					"CUSTOM_LOGGING=1",
 | 
										"CUSTOM_LOGGING=1",
 | 
				
			||||||
 | 
										"HAVE_REALPATH=1",
 | 
				
			||||||
				);
 | 
									);
 | 
				
			||||||
				HEADER_SEARCH_PATHS = "";
 | 
									HEADER_SEARCH_PATHS = "";
 | 
				
			||||||
				LIBRARY_SEARCH_PATHS = (
 | 
									LIBRARY_SEARCH_PATHS = (
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -79,6 +79,14 @@ extern "C"{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
using namespace tihmstar;
 | 
					using namespace tihmstar;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma mark helpers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern "C"{
 | 
				
			||||||
 | 
					    void irecv_event_cb(const irecv_device_event_t* event, void *userdata);
 | 
				
			||||||
 | 
					    void idevice_event_cb(const idevice_event_t *event, void *userdata);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma mark futurerestore
 | 
				
			||||||
 | 
					
 | 
				
			||||||
futurerestore::futurerestore(bool isUpdateInstall, bool isPwnDfu) : _isUpdateInstall(isUpdateInstall), _isPwnDfu(isPwnDfu){
 | 
					futurerestore::futurerestore(bool isUpdateInstall, bool isPwnDfu) : _isUpdateInstall(isUpdateInstall), _isPwnDfu(isPwnDfu){
 | 
				
			||||||
    _client = idevicerestore_client_new();
 | 
					    _client = idevicerestore_client_new();
 | 
				
			||||||
| 
						 | 
					@ -117,7 +125,6 @@ int futurerestore::getDeviceMode(bool reRequest){
 | 
				
			||||||
    if (!reRequest && _client->mode && _client->mode->index != MODE_UNKNOWN) {
 | 
					    if (!reRequest && _client->mode && _client->mode->index != MODE_UNKNOWN) {
 | 
				
			||||||
        return _client->mode->index;
 | 
					        return _client->mode->index;
 | 
				
			||||||
    }else{
 | 
					    }else{
 | 
				
			||||||
        normal_client_free(_client);
 | 
					 | 
				
			||||||
        dfu_client_free(_client);
 | 
					        dfu_client_free(_client);
 | 
				
			||||||
        recovery_client_free(_client);
 | 
					        recovery_client_free(_client);
 | 
				
			||||||
        return check_mode(_client);
 | 
					        return check_mode(_client);
 | 
				
			||||||
| 
						 | 
					@ -159,7 +166,6 @@ void futurerestore::putDeviceIntoRecovery(){
 | 
				
			||||||
    safeFree(_client->udid);
 | 
					    safeFree(_client->udid);
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    //these get also freed by destructor
 | 
					    //these get also freed by destructor
 | 
				
			||||||
    normal_client_free(_client);
 | 
					 | 
				
			||||||
    dfu_client_free(_client);
 | 
					    dfu_client_free(_client);
 | 
				
			||||||
    recovery_client_free(_client);
 | 
					    recovery_client_free(_client);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -551,57 +557,71 @@ void get_custom_component(struct idevicerestore_client_t* client, plist_t build_
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int futurerestore::doRestore(const char *ipsw){
 | 
					void futurerestore::doRestore(const char *ipsw){
 | 
				
			||||||
    int err = 0;
 | 
					    plist_t buildmanifest = NULL;
 | 
				
			||||||
    //some memory might not get freed if this function throws an exception, but you probably don't want to catch that anyway.
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    struct idevicerestore_client_t* client = _client;
 | 
					 | 
				
			||||||
    int unused;
 | 
					 | 
				
			||||||
    int result = 0;
 | 
					 | 
				
			||||||
    int delete_fs = 0;
 | 
					    int delete_fs = 0;
 | 
				
			||||||
    char* filesystem = NULL;
 | 
					    char* filesystem = NULL;
 | 
				
			||||||
    plist_t buildmanifest = NULL;
 | 
					    cleanup([&]{
 | 
				
			||||||
 | 
					        info("Cleaning up...\n");
 | 
				
			||||||
 | 
					        safeFreeCustom(buildmanifest, plist_free);
 | 
				
			||||||
 | 
					        if (delete_fs && filesystem) unlink(filesystem);
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    struct idevicerestore_client_t* client = _client;
 | 
				
			||||||
    plist_t build_identity = NULL;
 | 
					    plist_t build_identity = NULL;
 | 
				
			||||||
    plist_t sep_build_identity = NULL;
 | 
					    plist_t sep_build_identity = NULL;
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    client->ipsw = strdup(ipsw);
 | 
					    client->ipsw = strdup(ipsw);
 | 
				
			||||||
    if (!_isUpdateInstall) client->flags |= FLAG_ERASE;
 | 
					    if (!_isUpdateInstall) client->flags |= FLAG_ERASE;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    getDeviceMode(true);
 | 
					    irecv_device_event_subscribe(&client->irecv_e_ctx, irecv_event_cb, client);
 | 
				
			||||||
    info("Found device in %s mode\n", client->mode->string);
 | 
					    idevice_event_subscribe(idevice_event_cb, client);
 | 
				
			||||||
 | 
					    client->idevice_e_ctx = (void*)idevice_event_cb;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    retassure(client->mode->index == MODE_RECOVERY || (client->mode->index == MODE_DFU && _enterPwnRecoveryRequested), "device not in recovery mode\n");
 | 
					    mutex_lock(&client->device_event_mutex);
 | 
				
			||||||
 | 
					    cond_wait_timeout(&client->device_event_cond, &client->device_event_mutex, 10000);
 | 
				
			||||||
    // discover the device type
 | 
					 | 
				
			||||||
    retassure(check_hardware_model(client) && client->device, "ERROR: Unable to discover device model\n");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    info("Identified device as %s, %s\n", client->device->hardware_model, client->device->product_type);
 | 
					 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					    retassure(client->mode != &idevicerestore_modes[MODE_UNKNOWN],  "Unable to discover device mode. Please make sure a device is attached.\n");
 | 
				
			||||||
 | 
					    if (client->mode != &idevicerestore_modes[MODE_RECOVERY]) {
 | 
				
			||||||
 | 
					        retassure(client->mode == &idevicerestore_modes[MODE_DFU], "Device in unexpected mode detected!");
 | 
				
			||||||
 | 
					        retassure(_enterPwnRecoveryRequested, "Device in DFU mode detected, but we were expecting recovery mode!");
 | 
				
			||||||
 | 
					    }else{
 | 
				
			||||||
 | 
					        retassure(!_enterPwnRecoveryRequested, "--pwn-dfu was specified, but device found in recovery mode!");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    info("Found device in %s mode\n", client->mode->string);
 | 
				
			||||||
 | 
					    mutex_unlock(&client->device_event_mutex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    info("Identified device as %s, %s\n", getDeviceBoardNoCopy(), getDeviceModelNoCopy());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // verify if ipsw file exists
 | 
					    // verify if ipsw file exists
 | 
				
			||||||
    retassure(!access(client->ipsw, F_OK),"ERROR: Firmware file %s does not exist.\n", client->ipsw);
 | 
					    retassure(!access(client->ipsw, F_OK),"ERROR: Firmware file %s does not exist.\n", client->ipsw);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    info("Extracting BuildManifest from IPSW\n");
 | 
					    info("Extracting BuildManifest from IPSW\n");
 | 
				
			||||||
    retassure(!ipsw_extract_build_manifest(client->ipsw, &buildmanifest, &unused),"ERROR: Unable to extract BuildManifest from %s. Firmware file might be corrupt.\n", client->ipsw);
 | 
					    {
 | 
				
			||||||
 | 
					        int unused;
 | 
				
			||||||
 | 
					        retassure(!ipsw_extract_build_manifest(client->ipsw, &buildmanifest, &unused),"ERROR: Unable to extract BuildManifest from %s. Firmware file might be corrupt.\n", client->ipsw);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* check if device type is supported by the given build manifest */
 | 
					    /* check if device type is supported by the given build manifest */
 | 
				
			||||||
    retassure(!build_manifest_check_compatibility(buildmanifest, client->device->product_type),"ERROR: Could not make sure this firmware is suitable for the current device. Refusing to continue.\n");
 | 
					    retassure(!build_manifest_check_compatibility(buildmanifest, client->device->product_type),"ERROR: Could not make sure this firmware is suitable for the current device. Refusing to continue.\n");
 | 
				
			||||||
    /* print iOS information from the manifest */
 | 
					    /* print iOS information from the manifest */
 | 
				
			||||||
    build_manifest_get_version_information(buildmanifest, client);
 | 
					    build_manifest_get_version_information(buildmanifest, client);
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    info("Product Version: %s\n", client->version);
 | 
					    info("Product Version: %s\n", client->version);
 | 
				
			||||||
    info("Product Build: %s Major: %d\n", client->build, client->build_major);
 | 
					    info("Product Build: %s Major: %d\n", client->build, client->build_major);
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    client->image4supported = is_image4_supported(client);
 | 
					    client->image4supported = is_image4_supported(client);
 | 
				
			||||||
    info("Device supports Image4: %s\n", (client->image4supported) ? "true" : "false");
 | 
					    info("Device supports Image4: %s\n", (client->image4supported) ? "true" : "false");
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    if (_enterPwnRecoveryRequested) //we are in pwnDFU, so we don't need to check nonces
 | 
					    if (_enterPwnRecoveryRequested) //we are in pwnDFU, so we don't need to check nonces
 | 
				
			||||||
        client->tss = _aptickets.at(0);
 | 
					        client->tss = _aptickets.at(0);
 | 
				
			||||||
    else if (!(client->tss = nonceMatchesApTickets()))
 | 
					    else if (!(client->tss = nonceMatchesApTickets()))
 | 
				
			||||||
        reterror("Devicenonce does not match APTicket nonce\n");
 | 
					        reterror("Devicenonce does not match APTicket nonce\n");
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    plist_dict_remove_item(client->tss, "BBTicket");
 | 
					    plist_dict_remove_item(client->tss, "BBTicket");
 | 
				
			||||||
    plist_dict_remove_item(client->tss, "BasebandFirmware");
 | 
					    plist_dict_remove_item(client->tss, "BasebandFirmware");
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    retassure(build_identity = getBuildidentityWithBoardconfig(buildmanifest, client->device->hardware_model, _isUpdateInstall),"ERROR: Unable to find any build identities for IPSW\n");
 | 
					    retassure(build_identity = getBuildidentityWithBoardconfig(buildmanifest, client->device->hardware_model, _isUpdateInstall),"ERROR: Unable to find any build identities for IPSW\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (_client->image4supported) {
 | 
					    if (_client->image4supported) {
 | 
				
			||||||
| 
						 | 
					@ -612,7 +632,7 @@ int futurerestore::doRestore(const char *ipsw){
 | 
				
			||||||
                      "ERROR: Unable to find any build identities for SEP\n");
 | 
					                      "ERROR: Unable to find any build identities for SEP\n");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //this is the buildidentity used for restore
 | 
					    //this is the buildidentity used for restore
 | 
				
			||||||
    plist_t manifest = plist_dict_get_item(build_identity, "Manifest");
 | 
					    plist_t manifest = plist_dict_get_item(build_identity, "Manifest");
 | 
				
			||||||
| 
						 | 
					@ -620,7 +640,7 @@ int futurerestore::doRestore(const char *ipsw){
 | 
				
			||||||
    printf("checking APTicket to be valid for this restore...\n");
 | 
					    printf("checking APTicket to be valid for this restore...\n");
 | 
				
			||||||
    //if we are in pwnDFU, just use first apticket. no need to check nonces
 | 
					    //if we are in pwnDFU, just use first apticket. no need to check nonces
 | 
				
			||||||
    auto im4m = (_enterPwnRecoveryRequested || _rerestoreiOS9) ? _im4ms.at(0) : nonceMatchesIM4Ms();
 | 
					    auto im4m = (_enterPwnRecoveryRequested || _rerestoreiOS9) ? _im4ms.at(0) : nonceMatchesIM4Ms();
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    uint64_t deviceEcid = getDeviceEcid();
 | 
					    uint64_t deviceEcid = getDeviceEcid();
 | 
				
			||||||
    uint64_t im4mEcid = 0;
 | 
					    uint64_t im4mEcid = 0;
 | 
				
			||||||
    if (_client->image4supported) {
 | 
					    if (_client->image4supported) {
 | 
				
			||||||
| 
						 | 
					@ -631,25 +651,25 @@ int futurerestore::doRestore(const char *ipsw){
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    retassure(im4mEcid, "Failed to read ECID from APTicket\n");
 | 
					    retassure(im4mEcid, "Failed to read ECID from APTicket\n");
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    if (im4mEcid != deviceEcid) {
 | 
					    if (im4mEcid != deviceEcid) {
 | 
				
			||||||
        error("ECID inside APTicket does not match device ECID\n");
 | 
					        error("ECID inside APTicket does not match device ECID\n");
 | 
				
			||||||
        printf("APTicket is valid for %16llu (dec) but device is %16llu (dec)\n",im4mEcid,deviceEcid);
 | 
					        printf("APTicket is valid for %16llu (dec) but device is %16llu (dec)\n",im4mEcid,deviceEcid);
 | 
				
			||||||
        reterror("APTicket can't be used for restoring this device\n");
 | 
					        reterror("APTicket can't be used for restoring this device\n");
 | 
				
			||||||
    }else
 | 
					    }else
 | 
				
			||||||
        printf("Verified ECID in APTicket matches device ECID\n");
 | 
					        printf("Verified ECID in APTicket matches device ECID\n");
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    if (_client->image4supported) {
 | 
					    if (_client->image4supported) {
 | 
				
			||||||
        printf("checking APTicket to be valid for this restore...\n");
 | 
					        printf("checking APTicket to be valid for this restore...\n");
 | 
				
			||||||
        uint64_t deviceEcid = getDeviceEcid();
 | 
					        uint64_t deviceEcid = getDeviceEcid();
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
        if (im4mEcid != deviceEcid) {
 | 
					        if (im4mEcid != deviceEcid) {
 | 
				
			||||||
            error("ECID inside APTicket does not match device ECID\n");
 | 
					            error("ECID inside APTicket does not match device ECID\n");
 | 
				
			||||||
            printf("APTicket is valid for %16llu (dec) but device is %16llu (dec)\n",im4mEcid,deviceEcid);
 | 
					            printf("APTicket is valid for %16llu (dec) but device is %16llu (dec)\n",im4mEcid,deviceEcid);
 | 
				
			||||||
            reterror("APTicket can't be used for restoring this device\n");
 | 
					            reterror("APTicket can't be used for restoring this device\n");
 | 
				
			||||||
        }else
 | 
					        }else
 | 
				
			||||||
            printf("Verified ECID in APTicket matches device ECID\n");
 | 
					            printf("Verified ECID in APTicket matches device ECID\n");
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
        plist_t ticketIdentity = img4tool::getBuildIdentityForIm4m({im4m.first,im4m.second}, buildmanifest);
 | 
					        plist_t ticketIdentity = img4tool::getBuildIdentityForIm4m({im4m.first,im4m.second}, buildmanifest);
 | 
				
			||||||
        //TODO: make this nicer!
 | 
					        //TODO: make this nicer!
 | 
				
			||||||
        //for now a simple pointercompare should be fine, because both plist_t should point into the same buildidentity inside the buildmanifest
 | 
					        //for now a simple pointercompare should be fine, because both plist_t should point into the same buildidentity inside the buildmanifest
 | 
				
			||||||
| 
						 | 
					@ -658,7 +678,7 @@ int futurerestore::doRestore(const char *ipsw){
 | 
				
			||||||
            printf("BuildIdentity selected for restore:\n");
 | 
					            printf("BuildIdentity selected for restore:\n");
 | 
				
			||||||
            img4tool::printGeneralBuildIdentityInformation(build_identity);
 | 
					            img4tool::printGeneralBuildIdentityInformation(build_identity);
 | 
				
			||||||
            printf("\nBuildIdentiy valid for the APTicket:\n");
 | 
					            printf("\nBuildIdentiy valid for the APTicket:\n");
 | 
				
			||||||
            
 | 
					
 | 
				
			||||||
            if (ticketIdentity) img4tool::printGeneralBuildIdentityInformation(ticketIdentity),putchar('\n');
 | 
					            if (ticketIdentity) img4tool::printGeneralBuildIdentityInformation(ticketIdentity),putchar('\n');
 | 
				
			||||||
            else{
 | 
					            else{
 | 
				
			||||||
                printf("IM4M is not valid for any restore within the Buildmanifest\n");
 | 
					                printf("IM4M is not valid for any restore within the Buildmanifest\n");
 | 
				
			||||||
| 
						 | 
					@ -674,24 +694,24 @@ int futurerestore::doRestore(const char *ipsw){
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }else if (_enterPwnRecoveryRequested){
 | 
					    }else if (_enterPwnRecoveryRequested){
 | 
				
			||||||
        info("[WARNING] skipping ramdisk hash check, since device is in pwnDFU according to user\n");
 | 
					        info("[WARNING] skipping ramdisk hash check, since device is in pwnDFU according to user\n");
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
    }else{
 | 
					    }else{
 | 
				
			||||||
        info("[WARNING] full buildidentity check is not implemented, only comparing ramdisk hash.\n");
 | 
					        info("[WARNING] full buildidentity check is not implemented, only comparing ramdisk hash.\n");
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
        auto ticket = getRamdiskHashFromSCAB(im4m.first, im4m.second);
 | 
					        auto ticket = getRamdiskHashFromSCAB(im4m.first, im4m.second);
 | 
				
			||||||
        const char *tickethash = ticket.first;
 | 
					        const char *tickethash = ticket.first;
 | 
				
			||||||
        size_t tickethashSize = ticket.second;
 | 
					        size_t tickethashSize = ticket.second;
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
        uint64_t manifestDigestSize = 0;
 | 
					        uint64_t manifestDigestSize = 0;
 | 
				
			||||||
        char *manifestDigest = NULL;
 | 
					        char *manifestDigest = NULL;
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
        plist_t restoreRamdisk = plist_dict_get_item(manifest, "RestoreRamDisk");
 | 
					        plist_t restoreRamdisk = plist_dict_get_item(manifest, "RestoreRamDisk");
 | 
				
			||||||
        plist_t digest = plist_dict_get_item(restoreRamdisk, "Digest");
 | 
					        plist_t digest = plist_dict_get_item(restoreRamdisk, "Digest");
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
        plist_get_data_val(digest, &manifestDigest, &manifestDigestSize);
 | 
					        plist_get_data_val(digest, &manifestDigest, &manifestDigestSize);
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
        if (tickethashSize == manifestDigestSize && memcmp(tickethash, manifestDigest, tickethashSize) == 0){
 | 
					        if (tickethashSize == manifestDigestSize && memcmp(tickethash, manifestDigest, tickethashSize) == 0){
 | 
				
			||||||
            printf("Verified APTicket to be valid for this restore\n");
 | 
					            printf("Verified APTicket to be valid for this restore\n");
 | 
				
			||||||
            free(manifestDigest);
 | 
					            free(manifestDigest);
 | 
				
			||||||
| 
						 | 
					@ -701,25 +721,25 @@ int futurerestore::doRestore(const char *ipsw){
 | 
				
			||||||
            reterror("APTicket can't be used for this restore\n");
 | 
					            reterror("APTicket can't be used for this restore\n");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    if (_basebandbuildmanifest){
 | 
					    if (_basebandbuildmanifest){
 | 
				
			||||||
        if (!(client->basebandBuildIdentity = getBuildidentityWithBoardconfig(_basebandbuildmanifest, client->device->hardware_model, _isUpdateInstall))){
 | 
					        if (!(client->basebandBuildIdentity = getBuildidentityWithBoardconfig(_basebandbuildmanifest, client->device->hardware_model, _isUpdateInstall))){
 | 
				
			||||||
            retassure(client->basebandBuildIdentity = getBuildidentityWithBoardconfig(_basebandbuildmanifest, client->device->hardware_model, !_isUpdateInstall), "ERROR: Unable to find any build identities for Baseband\n");
 | 
					            retassure(client->basebandBuildIdentity = getBuildidentityWithBoardconfig(_basebandbuildmanifest, client->device->hardware_model, !_isUpdateInstall), "ERROR: Unable to find any build identities for Baseband\n");
 | 
				
			||||||
            info("[WARNING] Unable to find Baseband buildidentities for restore type %s, using fallback %s\n", (_isUpdateInstall) ? "Update" : "Erase",(!_isUpdateInstall) ? "Update" : "Erase");
 | 
					            info("[WARNING] Unable to find Baseband buildidentities for restore type %s, using fallback %s\n", (_isUpdateInstall) ? "Update" : "Erase",(!_isUpdateInstall) ? "Update" : "Erase");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
            
 | 
					
 | 
				
			||||||
        client->bbfwtmp = (char*)_basebandPath;
 | 
					        client->bbfwtmp = (char*)_basebandPath;
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
        plist_t bb_manifest = plist_dict_get_item(client->basebandBuildIdentity, "Manifest");
 | 
					        plist_t bb_manifest = plist_dict_get_item(client->basebandBuildIdentity, "Manifest");
 | 
				
			||||||
        plist_t bb_baseband = plist_copy(plist_dict_get_item(bb_manifest, "BasebandFirmware"));
 | 
					        plist_t bb_baseband = plist_copy(plist_dict_get_item(bb_manifest, "BasebandFirmware"));
 | 
				
			||||||
        plist_dict_set_item(manifest, "BasebandFirmware", bb_baseband);
 | 
					        plist_dict_set_item(manifest, "BasebandFirmware", bb_baseband);
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
        retassure(_client->basebandBuildIdentity, "BasebandBuildIdentity not loaded, refusing to continue");
 | 
					        retassure(_client->basebandBuildIdentity, "BasebandBuildIdentity not loaded, refusing to continue");
 | 
				
			||||||
    }else{
 | 
					    }else{
 | 
				
			||||||
        warning("WARNING: we don't have a basebandbuildmanifest, not flashing baseband!\n");
 | 
					        warning("WARNING: we don't have a basebandbuildmanifest, not flashing baseband!\n");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    if (_client->image4supported) {
 | 
					    if (_client->image4supported) {
 | 
				
			||||||
        plist_t sep_manifest = plist_dict_get_item(sep_build_identity, "Manifest");
 | 
					        plist_t sep_manifest = plist_dict_get_item(sep_build_identity, "Manifest");
 | 
				
			||||||
        plist_t sep_sep = plist_copy(plist_dict_get_item(sep_manifest, "SEP"));
 | 
					        plist_t sep_sep = plist_copy(plist_dict_get_item(sep_manifest, "SEP"));
 | 
				
			||||||
| 
						 | 
					@ -731,26 +751,25 @@ int futurerestore::doRestore(const char *ipsw){
 | 
				
			||||||
        plist_t digest = plist_dict_get_item(sep_sep, "Digest");
 | 
					        plist_t digest = plist_dict_get_item(sep_sep, "Digest");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        retassure(digest && plist_get_node_type(digest) == PLIST_DATA, "ERROR: can't find sep digest\n");
 | 
					        retassure(digest && plist_get_node_type(digest) == PLIST_DATA, "ERROR: can't find sep digest\n");
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
        plist_get_data_val(digest, reinterpret_cast<char **>(&sephash), &sephashlen);
 | 
					        plist_get_data_val(digest, reinterpret_cast<char **>(&sephash), &sephashlen);
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
        if (sephashlen == 20)
 | 
					        if (sephashlen == 20)
 | 
				
			||||||
            SHA1((unsigned char*)_client->sepfwdata, (unsigned int)_client->sepfwdatasize, genHash);
 | 
					            SHA1((unsigned char*)_client->sepfwdata, (unsigned int)_client->sepfwdatasize, genHash);
 | 
				
			||||||
        else
 | 
					        else
 | 
				
			||||||
            SHA384((unsigned char*)_client->sepfwdata, (unsigned int)_client->sepfwdatasize, genHash);
 | 
					            SHA384((unsigned char*)_client->sepfwdata, (unsigned int)_client->sepfwdatasize, genHash);
 | 
				
			||||||
        retassure(!memcmp(genHash, sephash, sephashlen), "ERROR: SEP does not match sepmanifest\n");
 | 
					        retassure(!memcmp(genHash, sephash, sephashlen), "ERROR: SEP does not match sepmanifest\n");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    /* print information about current build identity */
 | 
					    /* print information about current build identity */
 | 
				
			||||||
    build_identity_print_information(build_identity);
 | 
					    build_identity_print_information(build_identity);
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    //check for enterpwnrecovery, because we could be in DFU mode
 | 
					    //check for enterpwnrecovery, because we could be in DFU mode
 | 
				
			||||||
    if (_enterPwnRecoveryRequested){
 | 
					    if (_enterPwnRecoveryRequested){
 | 
				
			||||||
        retassure(getDeviceMode(true) == MODE_DFU, "unexpected device mode\n");
 | 
					        retassure(getDeviceMode(true) == MODE_DFU, "unexpected device mode\n");
 | 
				
			||||||
        enterPwnRecovery(build_identity);
 | 
					        enterPwnRecovery(build_identity);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    // Get filesystem name from build identity
 | 
					    // Get filesystem name from build identity
 | 
				
			||||||
    char* fsname = NULL;
 | 
					    char* fsname = NULL;
 | 
				
			||||||
    retassure(!build_identity_get_component_path(build_identity, "OS", &fsname), "ERROR: Unable get path for filesystem component\n");
 | 
					    retassure(!build_identity_get_component_path(build_identity, "OS", &fsname), "ERROR: Unable get path for filesystem component\n");
 | 
				
			||||||
| 
						 | 
					@ -775,23 +794,23 @@ int futurerestore::doRestore(const char *ipsw){
 | 
				
			||||||
    if (p) {
 | 
					    if (p) {
 | 
				
			||||||
        *p = '\0';
 | 
					        *p = '\0';
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    if (stat(tmpf, &st) < 0) {
 | 
					    if (stat(tmpf, &st) < 0) {
 | 
				
			||||||
        __mkdir(tmpf, 0755);
 | 
					        __mkdir(tmpf, 0755);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    strcat(tmpf, "/");
 | 
					    strcat(tmpf, "/");
 | 
				
			||||||
    strcat(tmpf, fsname);
 | 
					    strcat(tmpf, fsname);
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    memset(&st, '\0', sizeof(struct stat));
 | 
					    memset(&st, '\0', sizeof(struct stat));
 | 
				
			||||||
    if (stat(tmpf, &st) == 0) {
 | 
					    if (stat(tmpf, &st) == 0) {
 | 
				
			||||||
        off_t fssize = 0;
 | 
					        off_t fssize = 0;
 | 
				
			||||||
        ipsw_get_file_size(client->ipsw, fsname, &fssize);
 | 
					        ipsw_get_file_size(client->ipsw, fsname, (uint64_t*)&fssize);
 | 
				
			||||||
        if ((fssize > 0) && (st.st_size == fssize)) {
 | 
					        if ((fssize > 0) && (st.st_size == fssize)) {
 | 
				
			||||||
            info("Using cached filesystem from '%s'\n", tmpf);
 | 
					            info("Using cached filesystem from '%s'\n", tmpf);
 | 
				
			||||||
            filesystem = strdup(tmpf);
 | 
					            filesystem = strdup(tmpf);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    if (!filesystem) {
 | 
					    if (!filesystem) {
 | 
				
			||||||
        char extfn[1024];
 | 
					        char extfn[1024];
 | 
				
			||||||
        strcpy(extfn, tmpf);
 | 
					        strcpy(extfn, tmpf);
 | 
				
			||||||
| 
						 | 
					@ -800,7 +819,7 @@ int futurerestore::doRestore(const char *ipsw){
 | 
				
			||||||
        strcpy(lockfn, tmpf);
 | 
					        strcpy(lockfn, tmpf);
 | 
				
			||||||
        strcat(lockfn, ".lock");
 | 
					        strcat(lockfn, ".lock");
 | 
				
			||||||
        lock_info_t li;
 | 
					        lock_info_t li;
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
        lock_file(lockfn, &li);
 | 
					        lock_file(lockfn, &li);
 | 
				
			||||||
        FILE* extf = NULL;
 | 
					        FILE* extf = NULL;
 | 
				
			||||||
        if (access(extfn, F_OK) != 0) {
 | 
					        if (access(extfn, F_OK) != 0) {
 | 
				
			||||||
| 
						 | 
					@ -821,11 +840,11 @@ int futurerestore::doRestore(const char *ipsw){
 | 
				
			||||||
            fclose(extf);
 | 
					            fclose(extf);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        remove(lockfn);
 | 
					        remove(lockfn);
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
        // Extract filesystem from IPSW
 | 
					        // Extract filesystem from IPSW
 | 
				
			||||||
        info("Extracting filesystem from IPSW\n");
 | 
					        info("Extracting filesystem from IPSW\n");
 | 
				
			||||||
        retassure(!ipsw_extract_to_file_with_progress(client->ipsw, fsname, filesystem, 1),"ERROR: Unable to extract filesystem from IPSW\n");
 | 
					        retassure(!ipsw_extract_to_file_with_progress(client->ipsw, fsname, filesystem, 1),"ERROR: Unable to extract filesystem from IPSW\n");
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
        if (strstr(filesystem, ".extract")) {
 | 
					        if (strstr(filesystem, ".extract")) {
 | 
				
			||||||
            // rename <fsname>.extract to <fsname>
 | 
					            // rename <fsname>.extract to <fsname>
 | 
				
			||||||
            remove(tmpf);
 | 
					            remove(tmpf);
 | 
				
			||||||
| 
						 | 
					@ -834,27 +853,48 @@ int futurerestore::doRestore(const char *ipsw){
 | 
				
			||||||
            filesystem = strdup(tmpf);
 | 
					            filesystem = strdup(tmpf);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    if (_rerestoreiOS9) {
 | 
					    if (_rerestoreiOS9) {
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
        if (dfu_send_component(client, build_identity, "iBSS") < 0) {
 | 
					        if (dfu_send_component(client, build_identity, "iBSS") < 0) {
 | 
				
			||||||
            error("ERROR: Unable to send iBSS to device\n");
 | 
					 | 
				
			||||||
            irecv_close(client->dfu->client);
 | 
					            irecv_close(client->dfu->client);
 | 
				
			||||||
            client->dfu->client = NULL;
 | 
					            client->dfu->client = NULL;
 | 
				
			||||||
            return -1;
 | 
					            reterror("ERROR: Unable to send iBSS to device\n");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
        /* reconnect */
 | 
					        /* reconnect */
 | 
				
			||||||
        dfu_client_free(client);
 | 
					        dfu_client_free(client);
 | 
				
			||||||
        sleep(2);
 | 
					 | 
				
			||||||
        dfu_client_new(client);
 | 
					 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
 | 
					        debug("Waiting for device to disconnect...\n");
 | 
				
			||||||
 | 
					        cond_wait_timeout(&client->device_event_cond, &client->device_event_mutex, 10000);
 | 
				
			||||||
 | 
					        retassure((client->mode == &idevicerestore_modes[MODE_UNKNOWN] || (mutex_unlock(&client->device_event_mutex),0)), "Device did not disconnect. Possibly invalid iBSS. Reset device and try again");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        debug("Waiting for device to reconnect...\n");
 | 
				
			||||||
 | 
					        cond_wait_timeout(&client->device_event_cond, &client->device_event_mutex, 10000);
 | 
				
			||||||
 | 
					        retassure((client->mode == &idevicerestore_modes[MODE_DFU] || (mutex_unlock(&client->device_event_mutex),0)), "Device did not disconnect. Possibly invalid iBSS. Reset device and try again");
 | 
				
			||||||
 | 
					        mutex_unlock(&client->device_event_mutex);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        dfu_client_new(client);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* send iBEC */
 | 
					        /* send iBEC */
 | 
				
			||||||
        if (dfu_send_component(client, build_identity, "iBEC") < 0) {
 | 
					        if (dfu_send_component(client, build_identity, "iBEC") < 0) {
 | 
				
			||||||
            error("ERROR: Unable to send iBEC to device\n");
 | 
					 | 
				
			||||||
            irecv_close(client->dfu->client);
 | 
					            irecv_close(client->dfu->client);
 | 
				
			||||||
            client->dfu->client = NULL;
 | 
					            client->dfu->client = NULL;
 | 
				
			||||||
            return -1;
 | 
					            reterror("ERROR: Unable to send iBEC to device\n");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        dfu_client_free(client);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        debug("Waiting for device to disconnect...\n");
 | 
				
			||||||
 | 
					        cond_wait_timeout(&client->device_event_cond, &client->device_event_mutex, 10000);
 | 
				
			||||||
 | 
					        retassure((client->mode == &idevicerestore_modes[MODE_UNKNOWN] || (mutex_unlock(&client->device_event_mutex),0)), "Device did not disconnect. Possibly invalid iBEC. Reset device and try again");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        debug("Waiting for device to reconnect...\n");
 | 
				
			||||||
 | 
					        cond_wait_timeout(&client->device_event_cond, &client->device_event_mutex, 10000);
 | 
				
			||||||
 | 
					        retassure((client->mode == &idevicerestore_modes[MODE_RECOVERY] || (mutex_unlock(&client->device_event_mutex),0)), "Device did not disconnect. Possibly invalid iBEC. Reset device and try again");
 | 
				
			||||||
 | 
					        mutex_unlock(&client->device_event_mutex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
    }else{
 | 
					    }else{
 | 
				
			||||||
        if ((client->build_major > 8)) {
 | 
					        if ((client->build_major > 8)) {
 | 
				
			||||||
            if (!client->image4supported) {
 | 
					            if (!client->image4supported) {
 | 
				
			||||||
| 
						 | 
					@ -865,9 +905,9 @@ int futurerestore::doRestore(const char *ipsw){
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    if (_enterPwnRecoveryRequested){ //if pwnrecovery send all components decrypted, unless we're dealing with iOS 10
 | 
					    if (_enterPwnRecoveryRequested){ //if pwnrecovery send all components decrypted, unless we're dealing with iOS 10
 | 
				
			||||||
        if (!_client->image4supported) {
 | 
					        if (!_client->image4supported) {
 | 
				
			||||||
            if (strncmp(client->version, "10.", 3))
 | 
					            if (strncmp(client->version, "10.", 3))
 | 
				
			||||||
| 
						 | 
					@ -879,125 +919,25 @@ int futurerestore::doRestore(const char *ipsw){
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        printf("waiting for device to reconnect... ");
 | 
					        printf("waiting for device to reconnect... ");
 | 
				
			||||||
        recovery_client_free(client);
 | 
					        recovery_client_free(client);
 | 
				
			||||||
        /* this must be long enough to allow the device to run the iBEC */
 | 
					 | 
				
			||||||
        /* FIXME: Probably better to detect if the device is back then */
 | 
					 | 
				
			||||||
        sleep(7);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
   
 | 
					        debug("Waiting for device to disconnect...\n");
 | 
				
			||||||
    for (int i=0;getDeviceMode(true) != MODE_RECOVERY && i<40; i++) putchar('.'),usleep(USEC_PER_SEC*0.5);
 | 
					        cond_wait_timeout(&client->device_event_cond, &client->device_event_mutex, 10000);
 | 
				
			||||||
    putchar('\n');
 | 
					        retassure((client->mode == &idevicerestore_modes[MODE_UNKNOWN] || (mutex_unlock(&client->device_event_mutex),0)), "Device did not disconnect. Possibly invalid iBEC. Reset device and try again");
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    retassure(check_mode(client), "failed to reconnect to device in recovery (iBEC) mode\n");
 | 
					        debug("Waiting for device to reconnect...\n");
 | 
				
			||||||
    
 | 
					        cond_wait_timeout(&client->device_event_cond, &client->device_event_mutex, 10000);
 | 
				
			||||||
 | 
					        retassure((client->mode == &idevicerestore_modes[MODE_RECOVERY] || (mutex_unlock(&client->device_event_mutex),0)), "Device did not disconnect. Possibly invalid iBEC. Reset device and try again");
 | 
				
			||||||
 | 
					        mutex_unlock(&client->device_event_mutex);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    retassure(client->mode == &idevicerestore_modes[MODE_RECOVERY], "failed to reconnect to device in recovery (iBEC) mode\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //do magic
 | 
					    //do magic
 | 
				
			||||||
    if (_client->image4supported) get_sep_nonce(client, &client->sepnonce, &client->sepnonce_size);
 | 
					    if (_client->image4supported) get_sep_nonce(client, &client->sepnonce, &client->sepnonce_size);
 | 
				
			||||||
    get_ap_nonce(client, &client->nonce, &client->nonce_size);
 | 
					    get_ap_nonce(client, &client->nonce, &client->nonce_size);
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    get_ecid(client, &client->ecid);
 | 
					    get_ecid(client, &client->ecid);
 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    if (client->mode->index == MODE_RECOVERY) {
 | 
					 | 
				
			||||||
        retassure(client->srnm,"ERROR: could not retrieve device serial number. Can't continue.\n");
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (irecv_send_command(client->recovery->client, "bgcolor 0 255 0") != IRECV_E_SUCCESS) {
 | 
					 | 
				
			||||||
            error("ERROR: Unable to set bgcolor\n");
 | 
					 | 
				
			||||||
            return -1;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        info("[WARNING] Setting bgcolor to green! If you don't see a green screen, then your device didn't boot iBEC correctly\n");
 | 
					 | 
				
			||||||
        sleep(2); //show the user a green screen!
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        retassure(!recovery_enter_restore(client, build_identity),"ERROR: Unable to place device into restore mode\n");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        recovery_client_free(client);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    if (_client->image4supported) {
 | 
					 | 
				
			||||||
        retassure(!get_tss_response(client, sep_build_identity, &client->septss), "ERROR: Unable to get SHSH blobs for SEP\n");
 | 
					 | 
				
			||||||
        retassure(_client->sepfwdatasize && _client->sepfwdata, "SEP not loaded, refusing to continue");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    if (client->mode->index == MODE_RESTORE) {
 | 
					 | 
				
			||||||
        info("About to restore device... \n");
 | 
					 | 
				
			||||||
        retassure(!(result = restore_device(client, build_identity, filesystem)), "ERROR: Unable to restore device\n");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    info("Cleaning up...\n");
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
error:
 | 
					 | 
				
			||||||
    safeFree(client->sepfwdata);
 | 
					 | 
				
			||||||
    safeFreeCustom(buildmanifest,plist_free);
 | 
					 | 
				
			||||||
    if (delete_fs && filesystem) unlink(filesystem);
 | 
					 | 
				
			||||||
    if (!result && !err) info("DONE\n");
 | 
					 | 
				
			||||||
    return result ? abs(result) : err;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int futurerestore::doJustBoot(const char *ipsw, string bootargs){
 | 
					 | 
				
			||||||
    int err = 0;
 | 
					 | 
				
			||||||
    //some memory might not get freed if this function throws an exception, but you probably don't want to catch that anyway.
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    struct idevicerestore_client_t* client = _client;
 | 
					 | 
				
			||||||
    int unused;
 | 
					 | 
				
			||||||
    int result = 0;
 | 
					 | 
				
			||||||
    plist_t buildmanifest = NULL;
 | 
					 | 
				
			||||||
    plist_t build_identity = NULL;
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    client->ipsw = strdup(ipsw);
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    getDeviceMode(true);
 | 
					 | 
				
			||||||
    info("Found device in %s mode\n", client->mode->string);
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    retassure((client->mode->index == MODE_DFU || client->mode->index == MODE_RECOVERY) && _enterPwnRecoveryRequested, "device not in DFU/Recovery mode\n");
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    // discover the device type
 | 
					 | 
				
			||||||
    retassure(check_hardware_model(client) && client->device,"ERROR: Unable to discover device model\n");
 | 
					 | 
				
			||||||
    info("Identified device as %s, %s\n", client->device->hardware_model, client->device->product_type);
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    // verify if ipsw file exists
 | 
					 | 
				
			||||||
    retassure(!access(client->ipsw, F_OK), "ERROR: Firmware file %s does not exist.\n", client->ipsw);
 | 
					 | 
				
			||||||
    info("Extracting BuildManifest from IPSW\n");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    retassure(!ipsw_extract_build_manifest(client->ipsw, &buildmanifest, &unused),"ERROR: Unable to extract BuildManifest from %s. Firmware file might be corrupt.\n", client->ipsw);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /* check if device type is supported by the given build manifest */
 | 
					 | 
				
			||||||
    retassure(!build_manifest_check_compatibility(buildmanifest, client->device->product_type),"ERROR: Could not make sure this firmware is suitable for the current device. Refusing to continue.\n");
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    /* print iOS information from the manifest */
 | 
					 | 
				
			||||||
    build_manifest_get_version_information(buildmanifest, client);
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    info("Product Version: %s\n", client->version);
 | 
					 | 
				
			||||||
    info("Product Build: %s Major: %d\n", client->build, client->build_major);
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    client->image4supported = is_image4_supported(client);
 | 
					 | 
				
			||||||
    info("Device supports Image4: %s\n", (client->image4supported) ? "true" : "false");
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    retassure(build_identity = getBuildidentityWithBoardconfig(buildmanifest, client->device->hardware_model, 0),"ERROR: Unable to find any build identities for IPSW\n");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    /* print information about current build identity */
 | 
					 | 
				
			||||||
    build_identity_print_information(build_identity);
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    //check for enterpwnrecovery, because we could be in DFU mode
 | 
					 | 
				
			||||||
    retassure(_enterPwnRecoveryRequested, "enterPwnRecoveryRequested is not set, but required");
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
    retassure(getDeviceMode(true) == MODE_DFU || getDeviceMode(false) == MODE_RECOVERY, "unexpected device mode\n");
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    enterPwnRecovery(build_identity, bootargs);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    client->recovery_custom_component_function = get_custom_component;
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    for (int i=0;getDeviceMode(true) != MODE_RECOVERY && i<40; i++) putchar('.'),usleep(USEC_PER_SEC*0.5);
 | 
					 | 
				
			||||||
    putchar('\n');
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    retassure(check_mode(client), "failed to reconnect to device in recovery (iBEC) mode\n");
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    get_ecid(client, &client->ecid);
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    client->flags |= FLAG_BOOT;
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    if (client->mode->index == MODE_RECOVERY) {
 | 
					    if (client->mode->index == MODE_RECOVERY) {
 | 
				
			||||||
        retassure(client->srnm,"ERROR: could not retrieve device serial number. Can't continue.\n");
 | 
					        retassure(client->srnm,"ERROR: could not retrieve device serial number. Can't continue.\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1005,25 +945,120 @@ int futurerestore::doJustBoot(const char *ipsw, string bootargs){
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        info("[WARNING] Setting bgcolor to green! If you don't see a green screen, then your device didn't boot iBEC correctly\n");
 | 
					        info("[WARNING] Setting bgcolor to green! If you don't see a green screen, then your device didn't boot iBEC correctly\n");
 | 
				
			||||||
        sleep(2); //show the user a green screen!
 | 
					        sleep(2); //show the user a green screen!
 | 
				
			||||||
        client->image4supported = true; //dirty hack to not require apticket
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        retassure(!recovery_enter_restore(client, build_identity),"ERROR: Unable to place device into restore mode\n");
 | 
					        retassure(!recovery_enter_restore(client, build_identity),"ERROR: Unable to place device into restore mode\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        client->image4supported = false;
 | 
					 | 
				
			||||||
        recovery_client_free(client);
 | 
					        recovery_client_free(client);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (_client->image4supported) {
 | 
				
			||||||
 | 
					        retassure(!get_tss_response(client, sep_build_identity, &client->septss), "ERROR: Unable to get SHSH blobs for SEP\n");
 | 
				
			||||||
 | 
					        retassure(_client->sepfwdatasize && _client->sepfwdata, "SEP not loaded, refusing to continue");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    info("Cleaning up...\n");
 | 
					 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
error:
 | 
					    mutex_lock(&client->device_event_mutex);
 | 
				
			||||||
    safeFree(client->sepfwdata);
 | 
					    debug("Waiting for device to disconnect...\n");
 | 
				
			||||||
    safeFreeCustom(buildmanifest, plist_free);
 | 
					    cond_wait_timeout(&client->device_event_cond, &client->device_event_mutex, 180000);
 | 
				
			||||||
    if (!result && !err) info("DONE\n");
 | 
					    retassure((client->mode == &idevicerestore_modes[MODE_RESTORE] || (mutex_unlock(&client->device_event_mutex),0)), "Device failed to enter restore mode");
 | 
				
			||||||
    return result ? abs(result) : err;
 | 
					    mutex_unlock(&client->device_event_mutex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    info("About to restore device... \n");
 | 
				
			||||||
 | 
					    int result = 0;
 | 
				
			||||||
 | 
					    retassure(!(result = restore_device(client, build_identity, filesystem)), "ERROR: Unable to restore device\n");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int futurerestore::doJustBoot(const char *ipsw, string bootargs){
 | 
				
			||||||
 | 
					    reterror("not implemented");
 | 
				
			||||||
 | 
					//    int err = 0;
 | 
				
			||||||
 | 
					//    //some memory might not get freed if this function throws an exception, but you probably don't want to catch that anyway.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//    struct idevicerestore_client_t* client = _client;
 | 
				
			||||||
 | 
					//    int unused;
 | 
				
			||||||
 | 
					//    int result = 0;
 | 
				
			||||||
 | 
					//    plist_t buildmanifest = NULL;
 | 
				
			||||||
 | 
					//    plist_t build_identity = NULL;
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//    client->ipsw = strdup(ipsw);
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//    getDeviceMode(true);
 | 
				
			||||||
 | 
					//    info("Found device in %s mode\n", client->mode->string);
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//    retassure((client->mode->index == MODE_DFU || client->mode->index == MODE_RECOVERY) && _enterPwnRecoveryRequested, "device not in DFU/Recovery mode\n");
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//    // discover the device type
 | 
				
			||||||
 | 
					//    retassure(check_hardware_model(client) && client->device,"ERROR: Unable to discover device model\n");
 | 
				
			||||||
 | 
					//    info("Identified device as %s, %s\n", client->device->hardware_model, client->device->product_type);
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//    // verify if ipsw file exists
 | 
				
			||||||
 | 
					//    retassure(!access(client->ipsw, F_OK), "ERROR: Firmware file %s does not exist.\n", client->ipsw);
 | 
				
			||||||
 | 
					//    info("Extracting BuildManifest from IPSW\n");
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//    retassure(!ipsw_extract_build_manifest(client->ipsw, &buildmanifest, &unused),"ERROR: Unable to extract BuildManifest from %s. Firmware file might be corrupt.\n", client->ipsw);
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//    /* check if device type is supported by the given build manifest */
 | 
				
			||||||
 | 
					//    retassure(!build_manifest_check_compatibility(buildmanifest, client->device->product_type),"ERROR: Could not make sure this firmware is suitable for the current device. Refusing to continue.\n");
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//    /* print iOS information from the manifest */
 | 
				
			||||||
 | 
					//    build_manifest_get_version_information(buildmanifest, client);
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//    info("Product Version: %s\n", client->version);
 | 
				
			||||||
 | 
					//    info("Product Build: %s Major: %d\n", client->build, client->build_major);
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//    client->image4supported = is_image4_supported(client);
 | 
				
			||||||
 | 
					//    info("Device supports Image4: %s\n", (client->image4supported) ? "true" : "false");
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//    retassure(build_identity = getBuildidentityWithBoardconfig(buildmanifest, client->device->hardware_model, 0),"ERROR: Unable to find any build identities for IPSW\n");
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//    /* print information about current build identity */
 | 
				
			||||||
 | 
					//    build_identity_print_information(build_identity);
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//    //check for enterpwnrecovery, because we could be in DFU mode
 | 
				
			||||||
 | 
					//    retassure(_enterPwnRecoveryRequested, "enterPwnRecoveryRequested is not set, but required");
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//    retassure(getDeviceMode(true) == MODE_DFU || getDeviceMode(false) == MODE_RECOVERY, "unexpected device mode\n");
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//    enterPwnRecovery(build_identity, bootargs);
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//    client->recovery_custom_component_function = get_custom_component;
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//    for (int i=0;getDeviceMode(true) != MODE_RECOVERY && i<40; i++) putchar('.'),usleep(USEC_PER_SEC*0.5);
 | 
				
			||||||
 | 
					//    putchar('\n');
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//    retassure(check_mode(client), "failed to reconnect to device in recovery (iBEC) mode\n");
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//    get_ecid(client, &client->ecid);
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//    client->flags |= FLAG_BOOT;
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//    if (client->mode->index == MODE_RECOVERY) {
 | 
				
			||||||
 | 
					//        retassure(client->srnm,"ERROR: could not retrieve device serial number. Can't continue.\n");
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//        retassure(!irecv_send_command(client->recovery->client, "bgcolor 0 255 0"), "ERROR: Unable to set bgcolor\n");
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//        info("[WARNING] Setting bgcolor to green! If you don't see a green screen, then your device didn't boot iBEC correctly\n");
 | 
				
			||||||
 | 
					//        sleep(2); //show the user a green screen!
 | 
				
			||||||
 | 
					//        client->image4supported = true; //dirty hack to not require apticket
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//        retassure(!recovery_enter_restore(client, build_identity),"ERROR: Unable to place device into restore mode\n");
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//        client->image4supported = false;
 | 
				
			||||||
 | 
					//        recovery_client_free(client);
 | 
				
			||||||
 | 
					//    }
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//    info("Cleaning up...\n");
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//error:
 | 
				
			||||||
 | 
					//    safeFree(client->sepfwdata);
 | 
				
			||||||
 | 
					//    safeFreeCustom(buildmanifest, plist_free);
 | 
				
			||||||
 | 
					//    if (!result && !err) info("DONE\n");
 | 
				
			||||||
 | 
					//    return result ? abs(result) : err;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
futurerestore::~futurerestore(){
 | 
					futurerestore::~futurerestore(){
 | 
				
			||||||
    normal_client_free(_client);
 | 
					 | 
				
			||||||
    recovery_client_free(_client);
 | 
					    recovery_client_free(_client);
 | 
				
			||||||
    idevicerestore_client_free(_client);
 | 
					    idevicerestore_client_free(_client);
 | 
				
			||||||
    for (auto im4m : _im4ms){
 | 
					    for (auto im4m : _im4ms){
 | 
				
			||||||
| 
						 | 
					@ -1052,26 +1087,50 @@ void futurerestore::loadFirmwareTokens(){
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const char *futurerestore::getDeviceModelNoCopy(){
 | 
					const char *futurerestore::getDeviceModelNoCopy(){
 | 
				
			||||||
    if (!_client->device || !_client->device->product_type){
 | 
					    if (!_client->device || !_client->device->product_type){
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
        int mode = getDeviceMode(true);
 | 
					        int mode = getDeviceMode(true);
 | 
				
			||||||
        retassure(mode == MODE_NORMAL || mode == MODE_RECOVERY || mode == MODE_DFU, "unexpected device mode=%d\n",mode);
 | 
					        retassure(mode == MODE_NORMAL || mode == MODE_RECOVERY || mode == MODE_DFU, "unexpected device mode=%d\n",mode);
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        retassure(check_hardware_model(_client) && _client->device, "ERROR: Unable to discover device model\n");
 | 
					        switch (mode) {
 | 
				
			||||||
 | 
					        case MODE_RESTORE:
 | 
				
			||||||
 | 
					            _client->device = restore_get_irecv_device(_client);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case MODE_NORMAL:
 | 
				
			||||||
 | 
					            _client->device = normal_get_irecv_device(_client);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case MODE_DFU:
 | 
				
			||||||
 | 
					        case MODE_RECOVERY:
 | 
				
			||||||
 | 
					            _client->device = dfu_get_irecv_device(_client);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        default:
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    return _client->device->product_type;
 | 
					    return _client->device->product_type;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const char *futurerestore::getDeviceBoardNoCopy(){
 | 
					const char *futurerestore::getDeviceBoardNoCopy(){
 | 
				
			||||||
    if (!_client->device || !_client->device->hardware_model){
 | 
					    if (!_client->device || !_client->device->product_type){
 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        int mode = getDeviceMode(true);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        retassure(mode == MODE_NORMAL || mode == MODE_RECOVERY, "unexpected device mode=%d\n",mode);
 | 
					        int mode = getDeviceMode(true);
 | 
				
			||||||
 | 
					        retassure(mode == MODE_NORMAL || mode == MODE_RECOVERY || mode == MODE_DFU, "unexpected device mode=%d\n",mode);
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        retassure(check_hardware_model(_client) && _client->device, "ERROR: Unable to discover device model\n");
 | 
					        switch (mode) {
 | 
				
			||||||
 | 
					        case MODE_RESTORE:
 | 
				
			||||||
 | 
					            _client->device = restore_get_irecv_device(_client);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case MODE_NORMAL:
 | 
				
			||||||
 | 
					            _client->device = normal_get_irecv_device(_client);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case MODE_DFU:
 | 
				
			||||||
 | 
					        case MODE_RECOVERY:
 | 
				
			||||||
 | 
					            _client->device = dfu_get_irecv_device(_client);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        default:
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    return _client->device->hardware_model;
 | 
					    return _client->device->hardware_model;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -103,7 +103,7 @@ public:
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    uint64_t getBasebandGoldCertIDFromDevice();
 | 
					    uint64_t getBasebandGoldCertIDFromDevice();
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    int doRestore(const char *ipsw);
 | 
					    void doRestore(const char *ipsw);
 | 
				
			||||||
    int doJustBoot(const char *ipsw, std::string bootargs = "");
 | 
					    int doJustBoot(const char *ipsw, std::string bootargs = "");
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    ~futurerestore();
 | 
					    ~futurerestore();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -264,12 +264,11 @@ int main_r(int argc, const char * argv[]) {
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
        if (bootargs)
 | 
					        if (bootargs)
 | 
				
			||||||
            res = client.doJustBoot(ipsw,bootargs);
 | 
					            client.doJustBoot(ipsw,bootargs);
 | 
				
			||||||
        else
 | 
					        else
 | 
				
			||||||
            res = client.doRestore(ipsw);
 | 
					            client.doRestore(ipsw);
 | 
				
			||||||
    } catch (int error) {
 | 
					    } catch (tihmstar::exception &e) {
 | 
				
			||||||
        if (error == -20) error("maybe you forgot -w ?\n");
 | 
					        e.dump();
 | 
				
			||||||
        err = error;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    cout << "Done: restoring "<< (!res ? "succeeded" : "failed")<<"." <<endl;
 | 
					    cout << "Done: restoring "<< (!res ? "succeeded" : "failed")<<"." <<endl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue