summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/idevicerestore.c158
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");