diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/idevicerestore.c | 158 | 
1 files changed, 153 insertions, 5 deletions
| diff --git a/src/idevicerestore.c b/src/idevicerestore.c index d02864e..6733a59 100644 --- a/src/idevicerestore.c +++ b/src/idevicerestore.c @@ -156,10 +156,18 @@ int main(int argc, char* argv[]) {  	// extract buildmanifest  	plist_t buildmanifest = NULL; -	info("Extracting BuildManifest from IPSW\n"); -	if (ipsw_extract_build_manifest(ipsw, &buildmanifest, &tss_enabled) < 0) { -		error("ERROR: Unable to extract BuildManifest from %s\n", ipsw); -		return -1; +	if (client->flags & FLAG_CUSTOM) { +		info("Extracting Restore.plist from IPSW\n"); +		if (ipsw_extract_restore_plist(ipsw, &buildmanifest) < 0) { +			error("ERROR: Unable to extract Restore.plist from %s\n", ipsw); +			return -1; +		} +	} else { +		info("Extracting BuildManifest from IPSW\n"); +		if (ipsw_extract_build_manifest(ipsw, &buildmanifest, &tss_enabled) < 0) { +			error("ERROR: Unable to extract BuildManifest from %s\n", ipsw); +			return -1; +		}  	}  	/* check if device type is supported by the given build manifest */ @@ -183,7 +191,147 @@ int main(int argc, char* argv[]) {  	// choose whether this is an upgrade or a restore (default to upgrade)  	client->tss = NULL;  	plist_t build_identity = NULL; -	if (client->flags & FLAG_ERASE) { +	if (client->flags & FLAG_CUSTOM) { +		build_identity = plist_new_dict(); +		{ +			plist_t node; +			plist_t comp; +			plist_t info; +			plist_t manifest; + +			info = plist_new_dict(); +			plist_dict_insert_item(info, "RestoreBehavior", plist_new_string((client->flags & FLAG_ERASE) ? "Erase" : "Update")); +			plist_dict_insert_item(info, "Variant", plist_new_string((client->flags & FLAG_ERASE) ? "Customer Erase Install (IPSW)" : "Customer Upgrade Install (IPSW)")); +			plist_dict_insert_item(build_identity, "Info", info); + +			manifest = plist_new_dict(); + +			char tmpstr[256]; +			char p_all_flash[128]; +			char lcmodel[8]; +			strcpy(lcmodel, client->device->model); +			int x = 0; +			while (lcmodel[x]) { +				lcmodel[x] = tolower(lcmodel[x]); +				x++; +			} + +			sprintf(p_all_flash, "Firmware/all_flash/all_flash.%s.%s", lcmodel, "production"); +			strcpy(tmpstr, p_all_flash); +			strcat(tmpstr, "/manifest"); + +			// get all_flash file manifest +			char *files[16]; +			char *fmanifest = NULL; +			uint32_t msize = 0; +			if (ipsw_extract_to_memory(ipsw, tmpstr, &fmanifest, &msize) < 0) { +				error("ERROR: could not extract %s from IPSW\n", tmpstr); +				return -1; +			} + +			char *tok = strtok(fmanifest, "\r\n"); +			int fc = 0; +			while (tok) { +				files[fc++] = strdup(tok); +				if (fc >= 16) { +					break; +				} +				tok = strtok(NULL, "\r\n"); +			} +			free(fmanifest); + +			for (x = 0; x < fc; x++) { +				info = plist_new_dict(); +				strcpy(tmpstr, p_all_flash); +				strcat(tmpstr, "/"); +				strcat(tmpstr, files[x]); +				plist_dict_insert_item(info, "Path", plist_new_string(tmpstr)); +				comp = plist_new_dict(); +				plist_dict_insert_item(comp, "Info", info); +				const char* compname = get_component_name(files[x]); +				if (compname) { +					plist_dict_insert_item(manifest, compname, comp); +					if (!strncmp(files[x], "DeviceTree", 10)) { +						plist_dict_insert_item(manifest, "RestoreDeviceTree", plist_copy(comp)); +					} +				} else { +					error("WARNING: unhandled component %s\n", files[x]); +					plist_free(comp); +				} +				free(files[x]); +				files[x] = NULL; +			} + +			// add iBSS +			sprintf(tmpstr, "Firmware/dfu/iBSS.%s.%s.dfu", lcmodel, "RELEASE"); +			info = plist_new_dict(); +			plist_dict_insert_item(info, "Path", plist_new_string(tmpstr)); +			comp = plist_new_dict(); +			plist_dict_insert_item(comp, "Info", info); +			plist_dict_insert_item(manifest, "iBSS", comp); + +			// add iBEC +			sprintf(tmpstr, "Firmware/dfu/iBEC.%s.%s.dfu", lcmodel, "RELEASE"); +			info = plist_new_dict(); +			plist_dict_insert_item(info, "Path", plist_new_string(tmpstr)); +			comp = plist_new_dict(); +			plist_dict_insert_item(comp, "Info", info); +			plist_dict_insert_item(manifest, "iBEC", comp); + +			// add kernel cache +			node = plist_dict_get_item(buildmanifest, "KernelCachesByTarget"); +			if (node && (plist_get_node_type(node) == PLIST_DICT)) { +				char tt[4]; +				strncpy(tt, lcmodel, 3); +				tt[3] = 0; +				plist_t kdict = plist_dict_get_item(node, tt); +				if (kdict && (plist_get_node_type(kdict) == PLIST_DICT)) { +					plist_t kc = plist_dict_get_item(kdict, "Release"); +					if (kc && (plist_get_node_type(kc) == PLIST_STRING)) { +						info = plist_new_dict(); +						plist_dict_insert_item(info, "Path", plist_copy(kc)); +						comp = plist_new_dict(); +						plist_dict_insert_item(comp, "Info", info); +						plist_dict_insert_item(manifest, "KernelCache", comp); +						plist_dict_insert_item(manifest, "RestoreKernelCache", plist_copy(comp)); + +					} +				} +			} + +			// add ramdisk +			node = plist_dict_get_item(buildmanifest, "RestoreRamDisks"); +			if (node && (plist_get_node_type(node) == PLIST_DICT)) { +				plist_t rd = plist_dict_get_item(node, (client->flags & FLAG_ERASE) ? "User" : "Update"); +				if (rd && (plist_get_node_type(rd) == PLIST_STRING)) { +					info = plist_new_dict(); +					plist_dict_insert_item(info, "Path", plist_copy(rd)); +					comp = plist_new_dict(); +					plist_dict_insert_item(comp, "Info", info); +					plist_dict_insert_item(manifest, "RestoreRamDisk", comp); +				} +			} + +			// add OS filesystem +			node = plist_dict_get_item(buildmanifest, "SystemRestoreImages"); +			if (!node) { +				error("ERROR: missing SystemRestoreImages in Restore.plist\n"); +			} +			plist_t os = plist_dict_get_item(node, "User"); +			if (!os) { +				error("ERROR: missing filesystem in Restore.plist\n"); +			} else { +				info = plist_new_dict(); +				plist_dict_insert_item(info, "Path", plist_copy(os)); +				comp = plist_new_dict(); +				plist_dict_insert_item(comp, "Info", info); +				plist_dict_insert_item(manifest, "OS", comp); +			} + +			// finally add manifest +			plist_dict_insert_item(build_identity, "Manifest", manifest); +		} +	} else if (client->flags & FLAG_ERASE) {  		build_identity = build_manifest_get_build_identity(buildmanifest, 0);  		if (build_identity == NULL) {  			error("ERROR: Unable to find any build identities\n"); | 
