Closed skortela closed 2 years ago
I tested above patch with iPad Air 5th Gen.. It still fails, here is last lines from log:
... Sending IsFUDFirmware for iBootData... Checkpoint 4874 complete with code 0 Updating gas gauge software (47) Checkpoint 4294972161 complete with code 0 Updating gas gauge softwTSS server returned: STATUS=94&MESSAGE=This device isn't eligible for the requested build. ERROR: TSS request failed (status=94, message=This device isn't eligible for the requested build.) ERROR: Unable to fetch Timer1 ticket ERROR: restore_send_firmware_updater_data: Couldn't get AppleTypeCRetimer firmware data ERROR: Unable to send FirmwareUpdater data ERROR: Unable to successfully restore device
now it fails with different message:
... Sending Timer1 TSS request... Request URL set to https://gs.apple.com/TSS/controller?action=2 TSS server returned: STATUS=168&MESSAGE=An internal error occurred. ERROR: tss_send_request: Unhandled status code 168
Yes I figured it out. Wait a little for me to make a new patch!
Tested above patch. Still same error:
... Sending Timer1,Ticket TSS request... Request URL set to https://gs.apple.com/TSS/controller?action=2 TSS server returned: STATUS=168&MESSAGE=An internal error occurred. ERROR: tss_send_request: Unhandled status code 168
Did you run with debug output? I want to see the actual request that gets sent.
Tried to run with debug output but output wasn't very good (Timer TSS request was not shown completely).. Anyway, added code to dump Timer TSS request to a file. Here's link to file: https://www.dropbox.com/s/5nbr3fpj2n09og5/tssreq?dl=0
Here is output of 'idevicerestore -e -l &> output.txt' (Doesn't look quite OK though, not sure why) https://www.dropbox.com/s/04sdudr5l9lfiah/output.txt?dl=0
Ah OK I see what is missing, need to check the code again...
Final revised patch:
diff --git a/src/restore.c b/src/restore.c
index ef907ba..48eca78 100644
--- a/src/restore.c
+++ b/src/restore.c
@@ -2683,6 +2683,204 @@ static plist_t restore_get_tcon_firmware_data(restored_client_t restore, struct
return response;
}
+static plist_t restore_get_timer_firmware_data(restored_client_t restore, struct idevicerestore_client_t* client, plist_t build_identity, plist_t p_info)
+{
+ char comp_name[64];
+ char *comp_path = NULL;
+ plist_t comp_node = NULL;
+ unsigned char* component_data = NULL;
+ unsigned int component_size = 0;
+ ftab_t ftab = NULL;
+ ftab_t rftab = NULL;
+ uint32_t ftag = 0;
+ plist_t parameters = NULL;
+ plist_t request = NULL;
+ plist_t response = NULL;
+ plist_t node = NULL;
+ const char* ticket_name = NULL;
+ uint32_t tag = 0;
+ int ret;
+
+ /* create Timer request */
+ request = tss_request_new(NULL);
+ if (request == NULL) {
+ error("ERROR: Unable to create Timer TSS request\n");
+ return NULL;
+ }
+
+ parameters = plist_new_dict();
+
+ /* add manifest for current build_identity to parameters */
+ tss_parameters_add_from_manifest(parameters, build_identity);
+
+ plist_dict_set_item(parameters, "ApProductionMode", plist_new_bool(1));
+ if (client->image4supported) {
+ plist_dict_set_item(parameters, "ApSecurityMode", plist_new_bool(1));
+ plist_dict_set_item(parameters, "ApSupportsImg4", plist_new_bool(1));
+ } else {
+ plist_dict_set_item(parameters, "ApSupportsImg4", plist_new_bool(0));
+ }
+
+ /* add Timer,* tags from info dictionary to parameters */
+ plist_t info_array = plist_dict_get_item(p_info, "InfoArray");
+ if (!info_array) {
+ error("ERROR: Could not find InfoArray in info dictionary\n");
+ plist_free(parameters);
+ return NULL;
+ } else {
+ plist_t info_dict = plist_array_get_item(info_array, 0);
+ plist_t hwid = plist_dict_get_item(info_dict, "HardwareID");
+ uint64_t u64val;
+ uint8_t bval;
+ tag = (uint32_t)_plist_dict_get_uint(info_dict, "TagNumber");
+ char key[64];
+
+ plist_dict_set_item(parameters, "TagNumber", plist_new_uint(tag));
+ plist_t node = plist_dict_get_item(info_dict, "TicketName");
+ if (node) {
+ ticket_name = plist_get_string_ptr(node, NULL);
+ plist_dict_set_item(parameters, "TicketName", plist_copy(node));
+ }
+
+ sprintf(key, "Timer,ChipID,%u", tag);
+ u64val = _plist_dict_get_uint(hwid, "ChipID");
+ plist_dict_set_item(parameters, key, plist_new_uint(u64val));
+
+ sprintf(key, "Timer,BoardID,%u", tag);
+ u64val = _plist_dict_get_uint(hwid, "BoardID");
+ plist_dict_set_item(parameters, key, plist_new_uint(u64val));
+
+ sprintf(key, "Timer,ECID,%u", tag);
+ u64val = _plist_dict_get_uint(hwid, "ECID");
+ plist_dict_set_item(parameters, key, plist_new_uint(u64val));
+
+ plist_t p_nonce = plist_dict_get_item(hwid, "Nonce");
+ if (p_nonce) {
+ sprintf(key, "Timer,Nonce,%u", tag);
+ plist_dict_set_item(parameters, key, plist_copy(p_nonce));
+ }
+
+ sprintf(key, "Timer,SecurityMode,%u", tag);
+ bval = _plist_dict_get_bool(hwid, "SecurityMode");
+ plist_dict_set_item(parameters, key, plist_new_bool(bval));
+
+ sprintf(key, "Timer,SecurityDomain,%u", tag);
+ u64val = _plist_dict_get_uint(hwid, "SecurityDomain");
+ plist_dict_set_item(parameters, key, plist_new_uint(u64val));
+
+ sprintf(key, "Timer,ProductionMode,%u", tag);
+ u64val = _plist_dict_get_uint(hwid, "ProductionStatus");
+ plist_dict_set_item(parameters, key, plist_new_uint(u64val));
+ }
+ plist_t ap_info = plist_dict_get_item(p_info, "APInfo");
+ if (!ap_info) {
+ error("ERROR: Could not find APInfo in info dictionary\n");
+ plist_free(parameters);
+ return NULL;
+ } else {
+ plist_dict_merge(parameters, ap_info);
+ }
+
+ /* add required tags for Timer TSS request */
+ tss_request_add_timer_tags(request, parameters, NULL);
+
+ plist_free(parameters);
+
+ info("Sending %s TSS request...\n", ticket_name);
+ response = tss_request_send(request, client->tss_url);
+ plist_free(request);
+ if (response == NULL) {
+ error("ERROR: Unable to fetch %s\n", ticket_name);
+ return NULL;
+ }
+
+ if (plist_dict_get_item(response, ticket_name)) {
+ info("Received %s\n", ticket_name);
+ } else {
+ error("ERROR: No '%s' in TSS response, this might not work\n", ticket_name);
+ }
+
+ sprintf(comp_name, "Timer,RTKitOS,%u", tag);
+ if (build_identity_has_component(build_identity, comp_name)) {
+ if (build_identity_get_component_path(build_identity, comp_name, &comp_path) < 0) {
+ error("ERROR: Unable to get path for '%s' component\n", comp_name);
+ return NULL;
+ }
+ ret = extract_component(client->ipsw, comp_path, &component_data, &component_size);
+ free(comp_path);
+ comp_path = NULL;
+ if (ret < 0) {
+ error("ERROR: Unable to extract '%s' component\n", comp_name);
+ return NULL;
+ }
+ if (ftab_parse(component_data, component_size, &ftab, &ftag) != 0) {
+ free(component_data);
+ error("ERROR: Failed to parse '%s' component data.\n", comp_name);
+ return NULL;
+ }
+ free(component_data);
+ component_data = NULL;
+ component_size = 0;
+ if (ftag != 'rkos') {
+ error("WARNING: Unexpected tag 0x%08x, expected 0x%08x; continuing anyway.\n", ftag, 'rkos');
+ }
+ } else {
+ info("NOTE: Build identity does not have a '%s' component.\n", comp_name);
+ }
+
+ sprintf(comp_name, "Timer,RestoreRTKitOS,%u", tag);
+ if (build_identity_has_component(build_identity, comp_name)) {
+ if (build_identity_get_component_path(build_identity, comp_name, &comp_path) < 0) {
+ ftab_free(ftab);
+ error("ERROR: Unable to get path for '%s' component\n", comp_name);
+ return NULL;
+ }
+ ret = extract_component(client->ipsw, comp_path, &component_data, &component_size);
+ free(comp_path);
+ comp_path = NULL;
+ if (ret < 0) {
+ ftab_free(ftab);
+ error("ERROR: Unable to extract '%s' component\n", comp_name);
+ return NULL;
+ }
+
+ ftag = 0;
+ if (ftab_parse(component_data, component_size, &rftab, &ftag) != 0) {
+ free(component_data);
+ ftab_free(ftab);
+ error("ERROR: Failed to parse '%s' component data.\n", comp_name);
+ return NULL;
+ }
+ free(component_data);
+ component_data = NULL;
+ component_size = 0;
+ if (ftag != 'rkos') {
+ error("WARNING: Unexpected tag 0x%08x, expected 0x%08x; continuing anyway.\n", ftag, 'rkos');
+ }
+
+ if (ftab_get_entry_ptr(rftab, 'rrko', &component_data, &component_size) == 0) {
+ ftab_add_entry(ftab, 'rrko', component_data, component_size);
+ } else {
+ error("ERROR: Could not find 'rrko' entry in ftab. This will probably break things.\n");
+ }
+ ftab_free(rftab);
+ component_data = NULL;
+ component_size = 0;
+ } else {
+ info("NOTE: Build identity does not have a '%s' component.\n", comp_name);
+ }
+
+ ftab_write(ftab, &component_data, &component_size);
+ ftab_free(ftab);
+
+ plist_dict_set_item(response, "FirmwareData", plist_new_data((char *)component_data, (uint64_t)component_size));
+ free(component_data);
+ component_data = NULL;
+ component_size = 0;
+
+ return response;
+}
+
static int restore_send_firmware_updater_data(restored_client_t restore, struct idevicerestore_client_t* client, plist_t build_identity, plist_t message)
{
plist_t arguments;
@@ -2776,6 +2974,12 @@ static int restore_send_firmware_updater_data(restored_client_t restore, struct
error("ERROR: %s: Couldn't get AppleTCON firmware data\n", __func__);
goto error_out;
}
+ } else if (strcmp(s_updater_name, "AppleTypeCRetimer") == 0) {
+ fwdict = restore_get_timer_firmware_data(restore, client, build_identity, p_info);
+ if (fwdict == NULL) {
+ error("ERROR: %s: Couldn't get AppleTypeCRetimer firmware data\n", __func__);
+ goto error_out;
+ }
} else {
error("ERROR: %s: Got unknown updater name '%s'.\n", __func__, s_updater_name);
goto error_out;
diff --git a/src/tss.c b/src/tss.c
index 084ad10..9c3ad05 100644
--- a/src/tss.c
+++ b/src/tss.c
@@ -490,6 +490,48 @@ int tss_parameters_add_from_manifest(plist_t parameters, plist_t build_identity)
}
node = NULL;
+ /* add Timer,BoardID,1 */
+ node = plist_dict_get_item(build_identity, "Timer,BoardID,1");
+ if (node) {
+ plist_dict_set_item(parameters, "Timer,BoardID,1", plist_copy(node));
+ }
+ node = NULL;
+
+ /* add Timer,BoardID,2 */
+ node = plist_dict_get_item(build_identity, "Timer,BoardID,2");
+ if (node) {
+ plist_dict_set_item(parameters, "Timer,BoardID,2", plist_copy(node));
+ }
+ node = NULL;
+
+ /* add Timer,ChipID,1 */
+ node = plist_dict_get_item(build_identity, "Timer,ChipID,1");
+ if (node) {
+ plist_dict_set_item(parameters, "Timer,ChipID,1", plist_copy(node));
+ }
+ node = NULL;
+
+ /* add Timer,ChipID,2 */
+ node = plist_dict_get_item(build_identity, "Timer,ChipID,2");
+ if (node) {
+ plist_dict_set_item(parameters, "Timer,ChipID,2", plist_copy(node));
+ }
+ node = NULL;
+
+ /* add Timer,SecurityDomain,1 */
+ node = plist_dict_get_item(build_identity, "Timer,SecurityDomain,1");
+ if (node) {
+ plist_dict_set_item(parameters, "Timer,SecurityDomain,1", plist_copy(node));
+ }
+ node = NULL;
+
+ /* add Timer,SecurityDomain,2 */
+ node = plist_dict_get_item(build_identity, "Timer,SecurityDomain,2");
+ if (node) {
+ plist_dict_set_item(parameters, "Timer,SecurityDomain,2", plist_copy(node));
+ }
+ node = NULL;
+
/* add build identity manifest dictionary */
node = plist_dict_get_item(build_identity, "Manifest");
if (!node || plist_get_node_type(node) != PLIST_DICT) {
@@ -1810,6 +1852,112 @@ int tss_request_add_tcon_tags(plist_t request, plist_t parameters, plist_t overr
return 0;
}
+int tss_request_add_timer_tags(plist_t request, plist_t parameters, plist_t overrides)
+{
+ plist_t node = NULL;
+ uint64_t u64val = 0;
+ uint8_t bval = 0;
+ uint32_t tag = 0;
+ char *ticket_name = NULL;
+
+ plist_t manifest_node = plist_dict_get_item(parameters, "Manifest");
+ if (!manifest_node || plist_get_node_type(manifest_node) != PLIST_DICT) {
+ error("ERROR: %s: Unable to get restore manifest from parameters\n", __func__);
+ return -1;
+ }
+
+ /* add tags indicating we want to get the Timer ticket */
+ plist_dict_set_item(request, "@BBTicket", plist_new_bool(1));
+
+ node = plist_dict_get_item(parameters, "TicketName");
+ if (!node) {
+ error("ERROR: %s: Missing TicketName\n", __func__);
+ return -1;
+ }
+ char key[64];
+ sprintf(key, "@%s", plist_get_string_ptr(node, NULL));
+
+ plist_dict_set_item(request, key, plist_new_bool(1));
+
+ tag = (uint32_t)_plist_dict_get_uint(parameters, "TagNumber");
+
+ sprintf(key, "Timer,BoardID,%u", tag);
+ u64val = _plist_dict_get_uint(parameters, key);
+ plist_dict_set_item(request, key, plist_new_uint(u64val));
+
+ sprintf(key, "Timer,ChipID,%u", tag);
+ u64val = _plist_dict_get_uint(parameters, key);
+ plist_dict_set_item(request, key, plist_new_uint(u64val));
+
+ sprintf(key, "Timer,SecurityDomain,%u", tag);
+ u64val = _plist_dict_get_uint(parameters, key);
+ plist_dict_set_item(request, key, plist_new_uint(u64val));
+
+ sprintf(key, "Timer,SecurityMode,%u", tag);
+ bval = _plist_dict_get_bool(parameters, key);
+ plist_dict_set_item(request, key, plist_new_bool(bval));
+
+ sprintf(key, "Timer,ProductionMode,%u", tag);
+ bval = _plist_dict_get_bool(parameters, key);
+ plist_dict_set_item(request, key, plist_new_bool(bval));
+
+ sprintf(key, "Timer,ECID,%u", tag);
+ u64val = _plist_dict_get_uint(parameters, key);
+ plist_dict_set_item(request, key, plist_new_uint(u64val));
+
+ sprintf(key, "Timer,Nonce,%u", tag);
+ plist_t p_nonce = plist_dict_get_item(parameters, key);
+ plist_dict_set_item(request, key, plist_copy(p_nonce));
+
+ char *comp_name = NULL;
+ plist_dict_iter iter = NULL;
+ plist_dict_new_iter(manifest_node, &iter);
+ while (iter) {
+ node = NULL;
+ comp_name = NULL;
+ plist_dict_next_item(manifest_node, iter, &comp_name, &node);
+ if (comp_name == NULL) {
+ node = NULL;
+ break;
+ }
+ if (!strncmp(comp_name, "Timer,", 6)) {
+ plist_t manifest_entry = plist_copy(node);
+
+ /* handle RestoreRequestRules */
+ plist_t rules = plist_access_path(manifest_entry, 2, "Info", "RestoreRequestRules");
+ if (rules) {
+ debug("DEBUG: Applying restore request rules for entry %s\n", comp_name);
+ tss_entry_apply_restore_request_rules(manifest_entry, parameters, rules);
+ }
+
+ /* Make sure we have a Digest key for Trusted items even if empty */
+ plist_t node = plist_dict_get_item(manifest_entry, "Trusted");
+ if (node && plist_get_node_type(node) == PLIST_BOOLEAN) {
+ uint8_t trusted;
+ plist_get_bool_val(node, &trusted);
+ if (trusted && !plist_access_path(manifest_entry, 1, "Digest")) {
+ debug("DEBUG: No Digest data, using empty value for entry %s\n", comp_name);
+ plist_dict_set_item(manifest_entry, "Digest", plist_new_data(NULL, 0));
+ }
+ }
+
+ plist_dict_remove_item(manifest_entry, "Info");
+
+ /* finally add entry to request */
+ plist_dict_set_item(request, comp_name, manifest_entry);
+ }
+ free(comp_name);
+ }
+ free(iter);
+
+ /* apply overrides */
+ if (overrides) {
+ plist_dict_merge(&request, overrides);
+ }
+
+ return 0;
+}
+
static size_t tss_write_callback(char* data, size_t size, size_t nmemb, tss_response* response) {
size_t total = size * nmemb;
if (total != 0) {
diff --git a/src/tss.h b/src/tss.h
index 3590aed..8464f11 100644
--- a/src/tss.h
+++ b/src/tss.h
@@ -48,6 +48,7 @@ int tss_request_add_vinyl_tags(plist_t request, plist_t parameters, plist_t over
int tss_request_add_rose_tags(plist_t request, plist_t parameters, plist_t overrides);
int tss_request_add_veridian_tags(plist_t request, plist_t parameters, plist_t overrides);
int tss_request_add_tcon_tags(plist_t request, plist_t parameters, plist_t overrides);
+int tss_request_add_timer_tags(plist_t request, plist_t parameters, plist_t overrides);
int tss_request_add_ap_img4_tags(plist_t request, plist_t parameters);
int tss_request_add_ap_img3_tags(plist_t request, plist_t parameters);
Now it works, output: https://www.dropbox.com/s/uouznum277zmipl/output2.txt?dl=0
Great! Thanks for confirming. Will push the changes right away!
Note: I deleted the old patches to not have people play with incomplete patches.
See 7eaa1fa.
Thanks @nikias and @pekn. However this is still failing on my tests.
[10:04:40.378][19188] : ERROR: Unable to get (null)-FirmwarePreflightInfo from lockdownd
[10:04:40.378][19188] : ERROR: Unable to get FirmwarePreflightInfo
[10:04:40.379][19188] : Sending TSS request attempt 1... [10:04:41.053][19188] : TSS server returned: STATUS=8&MESSAGE=An internal error occurred.
[10:04:41.053][19188] : ERROR: TSS request failed (status=8, message=An internal error occurred.)
[10:04:41.053][19188] : ERROR: Unable to send TSS request
[10:04:41.054][19188] : ERROR: Unable to get SHSH blobs for this device
Yes that's on me, I broke the TSS in my "cleanup commit". Should work again after my fix https://github.com/libimobiledevice/idevicerestore/commit/ca44e4dab1ff5ebffa54859d7a6142f0ecbecc8e
However I would love to find out how to fix the FirmwarePreflightInfo thing, let me check the code...
@skortela can you hop on Telegram so we can look into it? Join our group https://t.me/libimobiledevice and then you can find me. Seems like
ideviceinfo -k FirmwarePreflightInfo
Doesn't return any data.
Works now. Thanks.
Erasing of iPad Air 5th gen fails.
idevicerestore.log idevicerestore_debug.log