Files
palera1n/src/dfuhelper.c
T

194 lines
5.4 KiB
C
Raw Normal View History

2023-01-16 16:17:41 +08:00
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <fcntl.h>
#include <stddef.h>
#include <stdbool.h>
#include <unistd.h>
#include <ctype.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/ioctl.h>
#include <signal.h>
#include <pthread.h>
#include <errno.h>
#include <inttypes.h>
#include <libimobiledevice/libimobiledevice.h>
#include <libimobiledevice/lockdown.h>
#include <libimobiledevice/diagnostics_relay.h>
#include <plist/plist.h>
#include <libirecovery.h>
#include <usbmuxd.h>
2023-01-28 20:54:06 +08:00
#include <ANSI-color-codes.h>
2023-02-06 01:03:29 +08:00
#include <palerain.h>
2023-01-16 16:17:41 +08:00
#define FORMAT_KEY_VALUE 1
#define FORMAT_XML 2
2023-01-30 19:16:53 +08:00
#define NOHOME (cpid == 0x8015 || (cpid == 0x8010 && (bdid == 0x08 || bdid == 0x0a || bdid == 0x0c || bdid == 0x0e)))
2023-01-16 16:17:41 +08:00
2023-02-01 20:10:18 +08:00
int dfuhelper_thr_running = false;
2023-01-16 16:17:41 +08:00
void step(int time, int time2, char *text, bool (*cond)(uint64_t), uint64_t cond_arg) {
for (int i = time2; i < time; i++) {
2023-02-07 16:19:06 +08:00
printf(CYN "\r\033[K%s (%d)" CRESET, text, time - i + time2);
2023-01-16 16:17:41 +08:00
fflush(stdout);
sleep(1);
2023-01-16 17:33:12 +08:00
if (cond != NULL && cond(cond_arg)) pthread_exit(NULL);
2023-01-16 16:17:41 +08:00
}
printf(CYN "\r%s (%d)" CRESET, text, time2);
if (time2 == 0) puts("");
}
int connected_normal_mode(const usbmuxd_device_info_t *usbmuxd_device) {
devinfo_t dev;
int ret;
ret = devinfo_cmd(&dev, usbmuxd_device->udid);
if (ret != 0) {
LOG(LOG_ERROR, "Unable to get device information");
return 0;
}
if (strcmp(dev.CPUArchitecture, "arm64")) {
devinfo_free(&dev);
LOG(LOG_WARNING, "Ignoring non-arm64 device...");
return -1;
}
2023-01-25 22:09:38 +08:00
if (!strncmp(dev.productType, "iPhone10,", strlen("iPhone10,"))) {
2023-01-25 22:13:39 +08:00
LOG(LOG_VERBOSE2, "Product %s requires passcode to be disabled", dev.productType);
2023-01-25 22:09:38 +08:00
unsigned char passcode_state = 0;
2023-01-16 16:17:41 +08:00
ret = passstat_cmd(&passcode_state, usbmuxd_device->udid);
if (ret != 0) {
LOG(LOG_ERROR, "Failed to get passcode state");
devinfo_free(&dev);
return -1;
}
if (passcode_state) {
LOG(LOG_ERROR, "Passcode must be disabled on this device");
2023-01-25 22:09:38 +08:00
LOG(LOG_ERROR, "Additionally, passcode must never be set since restore on iOS 16+");
2023-01-16 16:17:41 +08:00
devinfo_free(&dev);
return -1;
}
}
LOG(LOG_INFO, "Telling device with udid %s to enter recovery mode immediately", usbmuxd_device->udid);
enter_recovery_cmd(usbmuxd_device->udid);
devinfo_free(&dev);
return 0;
}
static bool conditional(uint64_t ecid) {
2023-01-30 21:41:15 +08:00
return get_ecid_wait_for_dfu() != ecid;
2023-01-16 16:17:41 +08:00
}
void* connected_recovery_mode(struct irecv_device_info* info) {
int ret;
2023-01-16 17:33:12 +08:00
uint64_t ecid;
2023-01-30 19:16:53 +08:00
uint32_t cpid, bdid;
cpid = info->cpid;
ecid = info->ecid;
bdid = info->bdid;
2023-01-16 16:17:41 +08:00
if (!cpid_is_arm64(info->cpid)) {
LOG(LOG_WARNING, "Ignoring non-arm64 device...");
return NULL;
}
2023-01-18 01:53:24 +08:00
sleep(1);
2023-01-16 16:17:41 +08:00
ret = autoboot_cmd(info->ecid);
if (ret) {
LOG(LOG_ERROR, "Cannot set auto-boot back to true");
return NULL;
}
LOG(LOG_INFO, "Press any key when ready for DFU mode");
getchar();
2023-02-06 17:33:08 -05:00
step(3, 0, "Get ready", NULL, 0);
2023-01-16 16:17:41 +08:00
if (NOHOME)
step(4, 2, "Hold volume down + side button", NULL, 0);
2023-01-16 16:17:41 +08:00
else
step(4, 2, "Hold home + power button", NULL, 0);
2023-01-30 21:41:15 +08:00
set_ecid_wait_for_dfu(info->ecid);
2023-01-16 16:17:41 +08:00
ret = exitrecv_cmd(info->ecid);
2023-01-30 19:03:01 +08:00
info = NULL;
2023-01-16 16:17:41 +08:00
if (ret) {
LOG(LOG_ERROR, "Cannot exit recovery mode");
2023-01-30 21:41:15 +08:00
set_ecid_wait_for_dfu(0);
2023-01-16 16:17:41 +08:00
return NULL;
}
2023-02-07 16:19:06 +08:00
printf("\r\033[K");
2023-01-16 16:17:41 +08:00
bool nohome = NOHOME;
if (nohome)
step(2, 0, "Hold volume down + side button", NULL, 0);
2023-01-16 16:17:41 +08:00
else
step(2, 0, "Hold home + power Button", NULL, 0);
2023-01-16 16:17:41 +08:00
if (nohome)
step(10, 0, "Hold volume down button", conditional, ecid);
2023-01-16 16:17:41 +08:00
else
step(10, 0, "Hold home button", conditional, ecid);
2023-01-30 21:41:15 +08:00
if (get_ecid_wait_for_dfu() != ecid) {
2023-01-16 16:17:41 +08:00
} else {
LOG(LOG_WARNING, "Whoops, device did not enter DFU mode");
LOG(LOG_INFO, "Waiting for device to reconnect...");
2023-01-30 21:41:15 +08:00
set_ecid_wait_for_dfu(0);
2023-01-16 16:17:41 +08:00
return NULL;
}
2023-01-30 21:41:15 +08:00
set_ecid_wait_for_dfu(0);
2023-01-17 13:46:42 +08:00
pthread_exit(NULL);
2023-01-16 16:17:41 +08:00
return NULL;
}
void* connected_dfu_mode(struct irecv_device_info* info) {
2023-01-30 21:41:15 +08:00
if (get_ecid_wait_for_dfu() == info->ecid) {
set_ecid_wait_for_dfu(0);
2023-01-17 20:48:54 +08:00
puts("");
2023-01-16 17:33:12 +08:00
LOG(LOG_INFO, "Device entered DFU mode successfully");
}
2023-01-16 16:17:41 +08:00
unsubscribe_cmd();
2023-01-30 21:41:15 +08:00
set_spin(0);
2023-01-17 13:46:42 +08:00
pthread_exit(NULL);
2023-01-16 16:17:41 +08:00
return NULL;
}
2023-01-22 21:12:30 +08:00
void device_event_cb(const usbmuxd_event_t *event, void* userdata) {
2023-01-18 00:44:47 +08:00
if (event->device.conn_type != CONNECTION_TYPE_USB) return;
2023-01-16 16:17:41 +08:00
switch (event->event) {
case UE_DEVICE_ADD:
LOG(LOG_VERBOSE, "Normal mode device connected");
connected_normal_mode(&event->device);
break;
case UE_DEVICE_REMOVE:
LOG(LOG_VERBOSE, "Normal mode device disconnected");
break;
}
}
2023-01-22 21:12:30 +08:00
void irecv_device_event_cb(const irecv_device_event_t *event, void* userdata) {
2023-01-16 16:17:41 +08:00
pthread_t recovery_thread, dfu_thread;
2023-01-16 17:33:12 +08:00
2023-01-16 16:17:41 +08:00
switch(event->type) {
case IRECV_DEVICE_ADD:
if (event->mode == IRECV_K_RECOVERY_MODE_1 || event->mode == IRECV_K_RECOVERY_MODE_2 || event->mode == IRECV_K_RECOVERY_MODE_3 || event->mode == IRECV_K_RECOVERY_MODE_4) {
LOG(LOG_VERBOSE, "Recovery mode device %ld connected", event->device_info->ecid);
pthread_create(&recovery_thread, NULL, (void* (*)(void*))connected_recovery_mode, event->device_info);
} else if (event->mode == IRECV_K_DFU_MODE) {
LOG(LOG_VERBOSE, "DFU mode device %ld connected", event->device_info->ecid);
pthread_create(&dfu_thread, NULL, (void* (*)(void*))connected_dfu_mode, event->device_info);
}
break;
case IRECV_DEVICE_REMOVE:
2023-01-30 21:41:15 +08:00
LOG(LOG_VERBOSE, "Recovery mode device disconnected");
2023-01-16 16:17:41 +08:00
break;
}
}
2023-01-22 21:12:30 +08:00
void *dfuhelper(void* ptr) {
2023-02-01 20:10:18 +08:00
dfuhelper_thr_running = true;
2023-01-16 16:17:41 +08:00
subscribe_cmd(device_event_cb, irecv_device_event_cb);
2023-01-30 21:41:15 +08:00
set_spin(1);
while (get_spin()) {
2023-01-16 16:17:41 +08:00
sleep(1);
};
2023-02-01 20:10:18 +08:00
dfuhelper_thr_running = false;
2023-01-16 16:17:41 +08:00
return 0;
}