diff options
Diffstat (limited to 'src/recovery.c')
-rw-r--r-- | src/recovery.c | 269 |
1 files changed, 269 insertions, 0 deletions
diff --git a/src/recovery.c b/src/recovery.c new file mode 100644 index 0000000..4e2e7ad --- /dev/null +++ b/src/recovery.c @@ -0,0 +1,269 @@ +/* + * recovery.c + * Functions for handling idevices in recovery mode + * + * Copyright (c) 2010 Joshua Hill. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <libirecovery.h> + +#include "tss.h" +#include "img3.h" +#include "recovery.h" +#include "idevicerestore.h" + +int recovery_send_signed_component(irecv_client_t client, char* ipsw, plist_t tss, char* component) { + int size = 0; + char* data = NULL; + char* path = NULL; + char* blob = NULL; + img3_file* img3 = NULL; + irecv_error_t error = 0; + + if (get_signed_component_by_name(ipsw, tss, component, &data, &size) < 0) { + error("ERROR: Unable to get signed component: %s\n", component); + return -1; + } + + info("Sending %s...\n", component); + error = irecv_send_buffer(client, data, size); + if (error != IRECV_E_SUCCESS) { + error("ERROR: Unable to send IMG3: %s\n", path); + img3_free(img3); + free(data); + free(path); + return -1; + } + + if (data) { + free(data); + data = NULL; + } + + return 0; +} + +irecv_error_t recovery_open_with_timeout(irecv_client_t* client) { + int i = 0; + irecv_error_t error = 0; + for (i = 10; i > 0; i--) { + error = irecv_open(client); + if (error == IRECV_E_SUCCESS) { + return error; + } + + sleep(2); + info("Retrying connection...\n"); + } + + error("ERROR: Unable to connect to recovery device.\n"); + return error; +} + +int recovery_send_ibec(char* ipsw, plist_t tss) { + irecv_error_t error = 0; + irecv_client_t client = NULL; + char* component = "iBEC"; + + error = recovery_open_with_timeout(&client); + if (error != IRECV_E_SUCCESS) { + return -1; + } + + error = irecv_send_command(client, "setenv auto-boot true"); + if (error != IRECV_E_SUCCESS) { + error("ERROR: Unable to set auto-boot environmental variable\n"); + irecv_close(client); + client = NULL; + return -1; + } + + error = irecv_send_command(client, "saveenv"); + if (error != IRECV_E_SUCCESS) { + error("ERROR: Unable to save environmental variable\n"); + irecv_close(client); + client = NULL; + return -1; + } + + if (recovery_send_signed_component(client, ipsw, tss, component) < 0) { + error("ERROR: Unable to send %s to device.\n", component); + irecv_close(client); + client = NULL; + return -1; + } + + error = irecv_send_command(client, "go"); + if (error != IRECV_E_SUCCESS) { + error("ERROR: Unable to execute %s\n", component); + irecv_close(client); + client = NULL; + return -1; + } + + if (client) { + irecv_close(client); + client = NULL; + } + return 0; +} + +int recovery_send_applelogo(char* ipsw, plist_t tss) { + irecv_error_t error = 0; + irecv_client_t client = NULL; + char* component = "AppleLogo"; + + info("Sending %s...\n", component); + + error = recovery_open_with_timeout(&client); + if (error != IRECV_E_SUCCESS) { + return -1; + } + + if (recovery_send_signed_component(client, ipsw, tss, component) < 0) { + error("ERROR: Unable to send %s to device.\n", component); + irecv_close(client); + client = NULL; + return -1; + } + + error = irecv_send_command(client, "setpicture 1"); + if (error != IRECV_E_SUCCESS) { + error("ERROR: Unable to set %s\n", component); + irecv_close(client); + client = NULL; + return -1; + } + + error = irecv_send_command(client, "bgcolor 0 0 0"); + if (error != IRECV_E_SUCCESS) { + error("ERROR: Unable to display %s\n", component); + irecv_close(client); + client = NULL; + return -1; + } + + if (client) { + irecv_close(client); + client = NULL; + } + return 0; +} + +int recovery_send_devicetree(char* ipsw, plist_t tss) { + irecv_error_t error = 0; + irecv_client_t client = NULL; + char *component = "RestoreDeviceTree"; + + error = recovery_open_with_timeout(&client); + if (error != IRECV_E_SUCCESS) { + return -1; + } + + if (recovery_send_signed_component(client, ipsw, tss, component) < 0) { + error("ERROR: Unable to send %s to device.\n", component); + irecv_close(client); + client = NULL; + return -1; + } + + error = irecv_send_command(client, "devicetree"); + if (error != IRECV_E_SUCCESS) { + error("ERROR: Unable to execute %s\n", component); + irecv_close(client); + client = NULL; + return -1; + } + + if (client) { + irecv_close(client); + client = NULL; + } + return 0; +} + +int recovery_send_ramdisk(char* ipsw, plist_t tss) { + irecv_error_t error = 0; + irecv_client_t client = NULL; + char *component = "RestoreRamDisk"; + + error = recovery_open_with_timeout(&client); + if (error != IRECV_E_SUCCESS) { + return -1; + } + + if (recovery_send_signed_component(client, ipsw, tss, component) < 0) { + error("ERROR: Unable to send %s to device.\n", component); + irecv_close(client); + client = NULL; + return -1; + } + + error = irecv_send_command(client, "ramdisk"); + if (error != IRECV_E_SUCCESS) { + error("ERROR: Unable to execute %s\n", component); + irecv_close(client); + client = NULL; + return -1; + } + + if (client) { + irecv_close(client); + client = NULL; + } + return 0; +} + +int recovery_send_kernelcache(char* ipsw, plist_t tss) { + irecv_error_t error = 0; + irecv_client_t client = NULL; + char *component = "RestoreKernelCache"; + + error = recovery_open_with_timeout(&client); + if (error != IRECV_E_SUCCESS) { + return -1; + } + + if (recovery_send_signed_component(client, ipsw, tss, component) < 0) { + error("ERROR: Unable to send %s to device.\n", component); + irecv_close(client); + client = NULL; + return -1; + } + + error = irecv_send_command(client, "bootx"); + if (error != IRECV_E_SUCCESS) { + error("ERROR: Unable to execute %s\n", component); + irecv_close(client); + client = NULL; + return -1; + } + + if (client) { + irecv_close(client); + client = NULL; + } + return 0; +} + + +int recovery_get_ecid(uint64_t* ecid) { + return 0; +} |