Пример #1
0
int recovery_send_kernelcache(struct idevicerestore_client_t* client, plist_t build_identity) {
	const char* component = "RestoreKernelCache";
	irecv_error_t recovery_error = IRECV_E_SUCCESS;

	if (client->recovery == NULL) {
		if (recovery_client_new(client) < 0) {
			return -1;
		}
	}

	if (recovery_send_component(client, build_identity, component) < 0) {
		error("ERROR: Unable to send %s to device.\n", component);
		return -1;
	}

	irecv_usb_control_transfer(client->recovery->client, 0x21, 1, 0, 0, 0, 0, 5000);

	if (client->restore_boot_args) {
		char setba[256];
		strcpy(setba, "setenv boot-args ");
		strcat(setba, client->restore_boot_args);
		recovery_error = irecv_send_command(client->recovery->client, setba);
	}

    if ((client->flags & FLAG_NOBOOTX) == 0) recovery_error = irecv_send_command(client->recovery->client, "bootx");
    else info("Flag nobootx detected! Not executing \"bootx\", but device is ready\n");
    
    if (recovery_error != IRECV_E_SUCCESS) {
		error("ERROR: Unable to execute %s\n", component);
		return -1;
	}

	return 0;
}
Пример #2
0
int irecv_control_transfer( irecv_client_t client,
							uint8_t bmRequestType,
							uint8_t bRequest,
							uint16_t wValue,
							uint16_t wIndex,
							unsigned char *data,
							uint16_t wLength,
							unsigned int timeout) {
#ifndef WIN32
	return irecv_usb_control_transfer(client->handle, bmRequestType, bRequest, wValue, wIndex, data, wLength, timeout);
#else
	DWORD count = 0;
	DWORD ret;
	BOOL bRet;
	OVERLAPPED overlapped;
	
	if (data == NULL) wLength = 0;
	
	usb_control_request* packet = (usb_control_request*) malloc(sizeof(usb_control_request) + wLength);
	packet->bmRequestType = bmRequestType;
	packet->bRequest = bRequest;
	packet->wValue = wValue;
	packet->wIndex = wIndex;
	packet->wLength = wLength;
	
	if (bmRequestType < 0x80 && wLength > 0) {
		memcpy(packet->data, data, wLength);
	}
	
	memset(&overlapped, 0, sizeof(overlapped));
	overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
	DeviceIoControl(client->handle, 0x2200A0, packet, sizeof(usb_control_request) + wLength, packet, sizeof(usb_control_request) + wLength, NULL, &overlapped);
	ret = WaitForSingleObject(overlapped.hEvent, timeout);
	bRet = GetOverlappedResult(client->handle, &overlapped, &count, FALSE);
	CloseHandle(overlapped.hEvent);
	if (!bRet) {
		CancelIo(client->handle);
		free(packet);
		return -1;
	}
	
	count -= sizeof(usb_control_request);
	if (count > 0) {
		if (bmRequestType >= 0x80) {
			memcpy(data, packet->data, count);
		}
	}
	free(packet);
	return count;
#endif
}
Пример #3
0
int recovery_send_ibec(struct idevicerestore_client_t* client, plist_t build_identity) {
	const char* component = "iBEC";
	irecv_error_t recovery_error = IRECV_E_SUCCESS;

	if (client->recovery == NULL) {
		if (recovery_client_new(client) < 0) {
			return -1;
		}
	}

	if (recovery_send_component(client, build_identity, component) < 0) {
		error("ERROR: Unable to send %s to device.\n", component);
		return -1;
	}

	recovery_error = irecv_send_command(client->recovery->client, "go");
	if (recovery_error != IRECV_E_SUCCESS) {
		error("ERROR: Unable to execute %s\n", component);
		return -1;
	}
	irecv_usb_control_transfer(client->recovery->client, 0x21, 1, 0, 0, 0, 0, 5000);

	return 0;
}
Пример #4
0
int dfu_enter_recovery(struct idevicerestore_client_t* client, plist_t build_identity) {
	irecv_error_t dfu_error = IRECV_E_SUCCESS;
	int mode = 0;

	if (dfu_client_new(client) < 0) {
		error("ERROR: Unable to connect to DFU device\n");
		return -1;
	}

	irecv_get_mode(client->dfu->client, &mode);

	if (mode != IRECV_K_DFU_MODE) {
		info("NOTE: device is not in DFU mode, assuming recovery mode.\n");
		client->mode = &idevicerestore_modes[MODE_RECOVERY];
		return 0;
	}

	if (dfu_send_component(client, build_identity, "iBSS") < 0) {
		error("ERROR: Unable to send iBSS to device\n");
		irecv_close(client->dfu->client);
		client->dfu->client = NULL;
		return -1;
	}

	irecv_usb_control_transfer(client->dfu->client, 0x21, 1, 0, 0, 0, 0, 5000);

	dfu_error = irecv_reset(client->dfu->client);
	if (dfu_error != IRECV_E_SUCCESS) {
		error("ERROR: Unable to reset device\n");
		irecv_close(client->dfu->client);
		client->dfu->client = NULL;
		return -1;
	}

	if (client->build_major > 8) {
		/* reconnect */
		dfu_client_free(client);
		sleep(2);
		dfu_client_new(client);

		/* get nonce */
		unsigned char* nonce = NULL;
		int nonce_size = 0;
		int nonce_changed = 0;
		if (dfu_get_ap_nonce(client, &nonce, &nonce_size) < 0) {
			error("ERROR: Unable to get ApNonce from device!\n");
			return -1;
		}

		if (!client->nonce || (nonce_size != client->nonce_size) || (memcmp(nonce, client->nonce, nonce_size) != 0)) {
			nonce_changed = 1;
			if (client->nonce) {
				free(client->nonce);
			}
			client->nonce = nonce;
			client->nonce_size = nonce_size;
		} else {
			free(nonce);
		}

		info("Nonce: ");
		int i;
		for (i = 0; i < client->nonce_size; i++) {
			info("%02x ", client->nonce[i]);
		}
		info("\n");

		if (nonce_changed && !(client->flags & FLAG_CUSTOM)) {
			// Welcome iOS5. We have to re-request the TSS with our nonce.
			plist_free(client->tss);
			if (get_tss_response(client, build_identity, &client->tss) < 0) {
				error("ERROR: Unable to get SHSH blobs for this device\n");
				return -1;
			}
			if (!client->tss) {
				error("ERROR: can't continue without TSS\n");
				return -1;
			}
			fixup_tss(client->tss);
		}

		if (irecv_usb_set_configuration(client->dfu->client, 1) < 0) {
			error("ERROR: set configuration failed\n");
		}

		/* send iBEC */
		if (dfu_send_component(client, build_identity, "iBEC") < 0) {
			error("ERROR: Unable to send iBEC to device\n");
			irecv_close(client->dfu->client);
			client->dfu->client = NULL;
			return -1;
		}

		irecv_usb_control_transfer(client->dfu->client, 0x21, 1, 0, 0, 0, 0, 5000);

		dfu_error = irecv_reset(client->dfu->client);
		if (dfu_error != IRECV_E_SUCCESS) {
			error("ERROR: Unable to reset device\n");
			irecv_close(client->dfu->client);
			client->dfu->client = NULL;
			return -1;
		}
	}

	dfu_client_free(client);

	sleep(7);

	// Reconnect to device, but this time make sure we're not still in DFU mode
	if (recovery_client_new(client) < 0) {
		error("ERROR: Unable to connect to recovery device\n");
		if (client->recovery->client) {
			irecv_close(client->recovery->client);
			client->recovery->client = NULL;
		}
		return -1;
	}

	irecv_get_mode(client->recovery->client, &mode);

	if (mode == IRECV_K_DFU_MODE) {
		error("ERROR: Unable to connect to recovery device\n");
		if (client->recovery->client) {
			irecv_close(client->recovery->client);
			client->recovery->client = NULL;
		}
		return -1;
	}

	return 0;
}