Refactor logging and add logfile support

idevicerestore will now also create a logfile automatically, unless
disabled with --logfile=NONE.
This commit is contained in:
Nikias Bassen
2025-06-23 14:00:10 +02:00
parent a5905b7f90
commit 8061f08b4e
24 changed files with 2014 additions and 1459 deletions
+4
View File
@@ -58,6 +58,10 @@ Prints usage information.
.B \-C, \-\-cache\-path DIR
Use specified directory for caching extracted or other reused files.
.TP
.B \-\-logfile PATH
Write logging output to file at PATH. If PATH equals \f[B]NULL\f[] or \f[B]NONE\f[],
no log file will be written. This disables automatic log file creation.
.TP
.B \-d, \-\-debug
Enable communication debugging.
.TP
+1
View File
@@ -29,6 +29,7 @@ bin_PROGRAMS = idevicerestore
idevicerestore_SOURCES = \
idevicerestore.c idevicerestore.h \
log.c log.h \
endianness.h \
common.c common.h \
fls.c fls.h \
+4 -4
View File
@@ -167,7 +167,7 @@ int ace3_create_binary(const unsigned char* uarp_fw, size_t uarp_size, uint64_t
uint64_t boardid = 0;
plist_get_uint_val(p_boardid, &boardid);
if (boardid == bdid) {
debug("DEBUG: %s: Found Board ID 0x%" PRIx64 "\n", __func__, bdid);
logger(LL_DEBUG, "%s: Found Board ID 0x%" PRIx64 "\n", __func__, bdid);
plist_t p4cc = plist_dict_get_item(payload, "Payload 4CC");
plist_get_string_val(p4cc, &payload_4cc);
plist_t matching = plist_dict_get_item(meta, "Personalization Matching Data");
@@ -189,7 +189,7 @@ int ace3_create_binary(const unsigned char* uarp_fw, size_t uarp_size, uint64_t
if (prev >= minrev && prev <= maxrev) {
plist_t tags = plist_dict_get_item(match, "Personalization Matching Data Payload Tags");
plist_get_string_val(tags, &data_payload_4ccs);
debug("DEBUG: %s: Found matching tags %s\n", __func__, data_payload_4ccs);
logger(LL_DEBUG, "%s: Found matching tags %s\n", __func__, data_payload_4ccs);
break;
}
} while (match);
@@ -201,11 +201,11 @@ int ace3_create_binary(const unsigned char* uarp_fw, size_t uarp_size, uint64_t
plist_mem_free(iter);
}
if (!payload_4cc) {
printf("Failed to get payload 4cc\n");
logger(LL_ERROR, "Failed to get payload 4cc\n");
return -1;
}
if (!data_payload_4ccs) {
printf("Failed to get data payload 4ccs\n");
logger(LL_ERROR, "Failed to get data payload 4ccs\n");
return -1;
}
+26 -27
View File
@@ -63,7 +63,7 @@ int asr_open_with_timeout(idevice_t device, asr_client_t* asr, uint16_t port)
if (port == 0) {
port = ASR_DEFAULT_PORT;
}
debug("Connecting to ASR on port %u\n", port);
logger(LL_VERBOSE, "Connecting to ASR on port %u\n", port);
for (i = 1; i <= attempts; i++) {
device_error = idevice_connect(device, port, &connection);
@@ -72,12 +72,12 @@ int asr_open_with_timeout(idevice_t device, asr_client_t* asr, uint16_t port)
}
if (i >= attempts) {
error("ERROR: Unable to connect to ASR client\n");
logger(LL_ERROR, "Unable to connect to ASR client\n");
return -1;
}
sleep(2);
debug("Retrying connection...\n");
logger(LL_VERBOSE, "Retrying connection...\n");
}
asr_client_t asr_loc = (asr_client_t)malloc(sizeof(struct asr_client));
@@ -88,7 +88,7 @@ int asr_open_with_timeout(idevice_t device, asr_client_t* asr, uint16_t port)
plist_t data = NULL;
asr_loc->checksum_chunks = 0;
if (asr_receive(asr_loc, &data) < 0) {
error("ERROR: Unable to receive data from ASR\n");
logger(LL_ERROR, "Unable to receive data from ASR\n");
asr_free(asr_loc);
plist_free(data);
return -1;
@@ -99,8 +99,8 @@ int asr_open_with_timeout(idevice_t device, asr_client_t* asr, uint16_t port)
char* strval = NULL;
plist_get_string_val(node, &strval);
if (strval && (strcmp(strval, "Initiate") != 0)) {
error("ERROR: unexpected ASR plist received:\n");
debug_plist(data);
logger(LL_ERROR, "Unexpected ASR plist received\n");
logger_dump_plist(LL_VERBOSE, data, 1);
plist_free(data);
asr_free(asr_loc);
return -1;
@@ -138,13 +138,13 @@ int asr_receive(asr_client_t asr, plist_t* data)
buffer = (char*)malloc(ASR_BUFFER_SIZE);
if (buffer == NULL) {
error("ERROR: Unable to allocate memory for ASR receive buffer\n");
logger(LL_ERROR, "Unable to allocate memory for ASR receive buffer\n");
return -1;
}
device_error = idevice_connection_receive(asr->connection, buffer, ASR_BUFFER_SIZE, &size);
if (device_error != IDEVICE_E_SUCCESS) {
error("ERROR: Unable to receive data from ASR\n");
logger(LL_ERROR, "Unable to receive data from ASR\n");
free(buffer);
return -1;
}
@@ -152,9 +152,8 @@ int asr_receive(asr_client_t asr, plist_t* data)
*data = request;
debug("Received %d bytes:\n", size);
if (idevicerestore_debug)
debug_plist(request);
logger(LL_DEBUG, "Received %d bytes:\n", size);
logger_dump_plist(LL_DEBUG, request, 1);
free(buffer);
return 0;
}
@@ -166,7 +165,7 @@ int asr_send(asr_client_t asr, plist_t data)
plist_to_xml(data, &buffer, &size);
if (asr_send_buffer(asr, buffer, size) < 0) {
error("ERROR: Unable to send plist to ASR\n");
logger(LL_ERROR, "Unable to send plist to ASR\n");
free(buffer);
return -1;
}
@@ -183,7 +182,7 @@ int asr_send_buffer(asr_client_t asr, const char* data, uint32_t size)
device_error = idevice_connection_send(asr->connection, data, size, &bytes);
if (device_error != IDEVICE_E_SUCCESS || bytes != size) {
error("ERROR: Unable to send data to ASR. Sent %u of %u bytes.\n", bytes, size);
logger(LL_ERROR, "Unable to send data to ASR. Sent %u of %u bytes.\n", bytes, size);
return -1;
}
@@ -240,19 +239,19 @@ int asr_perform_validation(asr_client_t asr, ipsw_file_handle_t file)
// Expected by device after every initiate
if (asr_send_validation_packet_info(asr, length) < 0) {
error("ERROR: Unable to send validation packet info to ASR\n");
logger(LL_ERROR, "Unable to send validation packet info to ASR\n");
return -1;
}
while (1) {
if (asr_receive(asr, &packet) < 0) {
error("ERROR: Unable to receive validation packet\n");
logger(LL_ERROR, "Unable to receive validation packet\n");
return -1;
}
if (packet == NULL) {
if (attempts < 5) {
info("Retrying to receive validation packet... %d\n", attempts);
logger(LL_INFO, "Retrying to receive validation packet... %d\n", attempts);
attempts++;
sleep(1);
continue;
@@ -263,7 +262,7 @@ int asr_perform_validation(asr_client_t asr, ipsw_file_handle_t file)
node = plist_dict_get_item(packet, "Command");
if (!node || plist_get_node_type(node) != PLIST_STRING) {
error("ERROR: Unable to find command node in validation request\n");
logger(LL_ERROR, "Unable to find command node in validation request\n");
return -1;
}
plist_get_string_val(node, &command);
@@ -279,7 +278,7 @@ int asr_perform_validation(asr_client_t asr, ipsw_file_handle_t file)
// Expected by device after every Initiate
if (asr_send_validation_packet_info(asr, length) < 0) {
error("ERROR: Unable to send validation packet info to ASR\n");
logger(LL_ERROR, "Unable to send validation packet info to ASR\n");
return -1;
}
@@ -297,7 +296,7 @@ int asr_perform_validation(asr_client_t asr, ipsw_file_handle_t file)
break;
} else {
error("ERROR: Unknown command received from ASR\n");
logger(LL_ERROR, "Unknown command received from ASR\n");
plist_free(packet);
return -1;
}
@@ -316,38 +315,38 @@ int asr_handle_oob_data_request(asr_client_t asr, plist_t packet, ipsw_file_hand
oob_length_node = plist_dict_get_item(packet, "OOB Length");
if (!oob_length_node || PLIST_UINT != plist_get_node_type(oob_length_node)) {
error("ERROR: Unable to find OOB data length\n");
logger(LL_ERROR, "Unable to find OOB data length\n");
return -1;
}
plist_get_uint_val(oob_length_node, &oob_length);
oob_offset_node = plist_dict_get_item(packet, "OOB Offset");
if (!oob_offset_node || PLIST_UINT != plist_get_node_type(oob_offset_node)) {
error("ERROR: Unable to find OOB data offset\n");
logger(LL_ERROR, "Unable to find OOB data offset\n");
return -1;
}
plist_get_uint_val(oob_offset_node, &oob_offset);
oob_data = (char*) malloc(oob_length);
if (oob_data == NULL) {
error("ERROR: Out of memory\n");
logger(LL_ERROR, "Out of memory\n");
return -1;
}
if (ipsw_file_seek(file, oob_offset, SEEK_SET) < 0) {
error("ERROR: Unable to seek to OOB offset 0x%" PRIx64 "\n", oob_offset);
logger(LL_ERROR, "Unable to seek to OOB offset 0x%" PRIx64 "\n", oob_offset);
free(oob_data);
return -1;
}
int64_t ir = ipsw_file_read(file, oob_data, oob_length);
if (ir != oob_length) {
error("ERROR: Unable to read OOB data from filesystem offset 0x%" PRIx64 ", oob_length %" PRIu64 ", read returned %" PRIi64"\n", oob_offset, oob_length, ir);
logger(LL_ERROR, "Unable to read OOB data from filesystem offset 0x%" PRIx64 ", oob_length %" PRIu64 ", read returned %" PRIi64"\n", oob_offset, oob_length, ir);
free(oob_data);
return -1;
}
if (asr_send_buffer(asr, oob_data, oob_length) < 0) {
error("ERROR: Unable to send OOB data to ASR\n");
logger(LL_ERROR, "Unable to send OOB data to ASR\n");
free(oob_data);
return -1;
}
@@ -377,7 +376,7 @@ int asr_send_payload(asr_client_t asr, ipsw_file_handle_t file)
}
if (ipsw_file_read(file, data, size) != (int64_t)size) {
error("Error reading filesystem\n");
logger(LL_ERROR, "Error reading filesystem\n");
retry--;
continue;
}
@@ -388,7 +387,7 @@ int asr_send_payload(asr_client_t asr, ipsw_file_handle_t file)
sendsize += 20;
}
if (asr_send_buffer(asr, data, sendsize) < 0) {
error("Unable to send filesystem payload chunk, retrying...\n");
logger(LL_ERROR, "Unable to send filesystem payload chunk, retrying...\n");
retry--;
continue;
}
+319 -142
View File
@@ -36,6 +36,7 @@
#include <fcntl.h>
#include <ctype.h>
#include <libimobiledevice-glue/thread.h>
#include <libimobiledevice-glue/collection.h>
#ifdef WIN32
#include <windows.h>
@@ -57,6 +58,13 @@
#define MAX_PRINT_LEN 64*1024
int global_quit_flag = 0;
static const char* STARS = "******************************************************************************";
static const char* SPACES = " ";
static const char* POUNDS = "##############################################################################";
static uint32_t progress_unique_tag = 1;
struct idevicerestore_mode_t idevicerestore_modes[] = {
{ 0, "Unknown" },
{ 1, "WTF" },
@@ -69,122 +77,17 @@ struct idevicerestore_mode_t idevicerestore_modes[] = {
int idevicerestore_debug = 0;
#define idevicerestore_err_buff_size 256
static char idevicerestore_err_buff[idevicerestore_err_buff_size] = {0, };
static FILE* info_stream = NULL;
static FILE* error_stream = NULL;
static FILE* debug_stream = NULL;
static int info_disabled = 0;
static int error_disabled = 0;
static int debug_disabled = 0;
static mutex_t log_mutex;
static thread_once_t init_once = THREAD_ONCE_INIT;
static void _log_init(void)
{
mutex_init(&log_mutex);
}
void info(const char* format, ...)
{
if (info_disabled) return;
thread_once(&init_once, _log_init);
mutex_lock(&log_mutex);
va_list vargs;
va_start(vargs, format);
vfprintf((info_stream) ? info_stream : stdout, format, vargs);
va_end(vargs);
fflush(info_stream?info_stream:stdout);
mutex_unlock(&log_mutex);
}
void error(const char* format, ...)
{
thread_once(&init_once, _log_init);
mutex_lock(&log_mutex);
va_list vargs, vargs2;
va_start(vargs, format);
va_copy(vargs2, vargs);
vsnprintf(idevicerestore_err_buff, idevicerestore_err_buff_size, format, vargs);
va_end(vargs);
if (!error_disabled) {
vfprintf((error_stream) ? error_stream : stderr, format, vargs2);
}
va_end(vargs2);
fflush(error_stream?error_stream:stderr);
mutex_unlock(&log_mutex);
}
void debug(const char* format, ...)
{
if (debug_disabled) return;
if (!idevicerestore_debug) {
return;
}
thread_once(&init_once, _log_init);
mutex_lock(&log_mutex);
va_list vargs;
va_start(vargs, format);
vfprintf((debug_stream) ? debug_stream : stderr, format, vargs);
va_end(vargs);
fflush(debug_stream?debug_stream:stderr);
mutex_unlock(&log_mutex);
}
void idevicerestore_set_info_stream(FILE* strm)
{
if (strm) {
info_disabled = 0;
info_stream = strm;
} else {
info_disabled = 1;
}
}
void idevicerestore_set_error_stream(FILE* strm)
{
if (strm) {
error_disabled = 0;
error_stream = strm;
} else {
error_disabled = 1;
}
}
void idevicerestore_set_debug_stream(FILE* strm)
{
if (strm) {
debug_disabled = 0;
debug_stream = strm;
} else {
debug_disabled = 1;
}
}
const char* idevicerestore_get_error(void)
{
if (idevicerestore_err_buff[0] == 0) {
return NULL;
} else {
char* p = NULL;
while ((strlen(idevicerestore_err_buff) > 0) && (p = strrchr(idevicerestore_err_buff, '\n'))) {
p[0] = '\0';
}
return (const char*)idevicerestore_err_buff;
}
}
static void (*banner_func)(const char*) = NULL;
static void (*banner_hide_func)(void) = NULL;
int write_file(const char* filename, const void* data, size_t size) {
size_t bytes = 0;
FILE* file = NULL;
debug("Writing data to %s\n", filename);
logger(LL_DEBUG, "Writing data to %s\n", filename);
file = fopen(filename, "wb");
if (file == NULL) {
error("write_file: Unable to open file %s\n", filename);
logger(LL_ERROR, "write_file: Unable to open file %s\n", filename);
return -1;
}
@@ -192,7 +95,7 @@ int write_file(const char* filename, const void* data, size_t size) {
fclose(file);
if (bytes != size) {
error("ERROR: Unable to write entire file: %s: %d of %d\n", filename, (int)bytes, (int)size);
logger(LL_ERROR, "Unable to write entire file: %s: %d of %d\n", filename, (int)bytes, (int)size);
return -1;
}
@@ -206,26 +109,26 @@ int read_file(const char* filename, void** data, size_t* size) {
char* buffer = NULL;
struct stat fst;
debug("Reading data from %s\n", filename);
logger(LL_DEBUG, "Reading data from %s\n", filename);
*size = 0;
*data = NULL;
file = fopen(filename, "rb");
if (file == NULL) {
error("read_file: cannot open %s: %s\n", filename, strerror(errno));
logger(LL_ERROR, "read_file: cannot open %s: %s\n", filename, strerror(errno));
return -1;
}
if (fstat(fileno(file), &fst) < 0) {
error("read_file: fstat: %s\n", strerror(errno));
logger(LL_ERROR, "read_file: fstat: %s\n", strerror(errno));
return -1;
}
length = fst.st_size;
buffer = (char*) malloc(length);
if (buffer == NULL) {
error("ERROR: Out of memory\n");
logger(LL_ERROR, "Out of memory\n");
fclose(file);
return -1;
}
@@ -233,7 +136,7 @@ int read_file(const char* filename, void** data, size_t* size) {
fclose(file);
if (bytes != length) {
error("ERROR: Unable to read entire file\n");
logger(LL_ERROR, "Unable to read entire file\n");
free(buffer);
return -1;
}
@@ -243,32 +146,309 @@ int read_file(const char* filename, void** data, size_t* size) {
return 0;
}
void debug_plist(plist_t plist) {
uint32_t size = 0;
char* data = NULL;
plist_to_xml(plist, &data, &size);
if (size <= MAX_PRINT_LEN)
info("printing %i bytes plist:\n%s", size, data);
else
info("supressed printing %i bytes plist...\n", size);
free(data);
int process_text_lines(const char* text, int maxwidth, struct tuple** lines_out, int* maxlen_out)
{
if (!text) return 0;
int len = strlen(text);
int numlines = 0;
int maxlen = 0;
int linestart = 0;
int linelen = 0;
int lastspace = 0;
int maxlines = 8;
int count = 0;
struct tuple* lines = (struct tuple*)malloc(sizeof(struct tuple) * maxlines);
int i = 0;
while (i <= len) {
int split_line = 0;
if ((text[i] & 0xE0) == 0xC0) i += 1;
else if ((text[i] & 0xF0) == 0xE0) i += 2;
else if ((text[i] & 0xF8) == 0xF0) i += 3;
if (i > len) i = len;
linelen = i - linestart;
if (text[i] == '\0') {
split_line = 1;
}
if (linelen > maxwidth) {
if (lastspace > linestart+maxwidth/2+6) {
count -= i-lastspace;
i = lastspace;
linelen = i - linestart;
split_line = 1;
} else {
split_line = 1;
}
}
if ((linelen > 0 && split_line) || text[i] == '\n') {
split_line = 0;
if (numlines == maxlines) {
maxlines += 8;
struct tuple* newlines = (struct tuple*)realloc(lines, sizeof(struct tuple) * maxlines);
if (!newlines) {
printf("FATAL: Out of memory\n");
return -1;
}
lines = newlines;
}
lines[numlines].idx = linestart;
lines[numlines].len = linelen;
lines[numlines].plen = count;
if (count > maxlen) maxlen = count;
numlines++;
linestart = i+1;
count = 0;
}
else if (text[i] == ' ') {
lastspace = i;
count++;
} else {
count++;
}
i++;
}
*lines_out = lines;
*maxlen_out = maxlen;
return numlines;
}
void print_progress_bar(double progress) {
#ifndef WIN32
if (info_disabled) return;
int i = 0;
if(progress < 0) return;
if(progress > 100) progress = 100;
fprintf((info_stream) ? info_stream : stdout, "\r[");
for(i = 0; i < 50; i++) {
if(i < progress / 2) fprintf((info_stream) ? info_stream : stdout, "=");
else fprintf((info_stream) ? info_stream : stdout, " ");
void set_banner_funcs(void (*showfunc)(const char*), void (*hidefunc)(void))
{
banner_func = showfunc;
banner_hide_func = hidefunc;
}
void show_banner(const char* text)
{
if (banner_func) {
banner_func(text);
} else {
int i;
int maxlen = 0;
struct tuple* lines = NULL;
int numlines = process_text_lines(text, 74, &lines, &maxlen);
printf("%.*s\n", maxlen + 4, STARS);
for (i = 0; i < numlines; i++) {
printf("* %.*s%.*s *\n", lines[i].len, text + lines[i].idx, maxlen-lines[i].plen, SPACES);
}
printf("%.*s\n", maxlen + 4, STARS);
free(lines);
}
fprintf((info_stream) ? info_stream : stdout, "] %5.1f%%", progress);
if(progress >= 100) fprintf((info_stream) ? info_stream : stdout, "\n");
fflush((info_stream) ? info_stream : stdout);
#endif
}
void hide_banner()
{
if (banner_hide_func) {
banner_hide_func();
}
}
static int (*prompt_func)(const char* title, const char* text) = NULL;
void set_prompt_func(int (*func)(const char* title, const char* text))
{
prompt_func = func;
}
int prompt_user(const char* title, const char* text)
{
if (!text) return -1;
if (prompt_func) {
return prompt_func(title, text);
}
int i;
int result = 0;
int maxlen = 0;
struct tuple* lines = NULL;
int numlines = process_text_lines(text, 74, &lines, &maxlen);
int outerlen = maxlen+4;
int titlelen = (title) ? strlen(title) : 0;
if (titlelen > 0) {
int lefttitlelen = (titlelen+4)/2;
int righttitlelen = titlelen+4 - lefttitlelen;
int leftpounds = outerlen/2 - lefttitlelen;
int rightpounds = outerlen-(titlelen+4) - leftpounds;
printf("%.*s[ %.*s ]%.*s\n", leftpounds, POUNDS, titlelen, title, rightpounds, POUNDS);
} else {
printf("%.*s\n", outerlen, POUNDS);
}
for (i = 0; i < numlines; i++) {
printf("%c %.*s%.*s %c\n", *POUNDS, lines[i].len, text + lines[i].idx, maxlen-lines[i].plen, SPACES, *POUNDS);
}
free(lines);
const char* yesmsg = "Type YES and press ENTER to continue, or hit CTRL+C to cancel.";
int ylen = strlen(yesmsg);
printf("%c %.*s%.*s %c\n", *POUNDS, ylen, yesmsg, maxlen-ylen, SPACES, *POUNDS);
printf("%.*s\n", outerlen, POUNDS);
char input[64];
while (1) {
printf("> ");
fflush(stdout);
fflush(stdin);
input[0] = '\0';
get_user_input(input, 63, 0);
if (global_quit_flag) {
result = -1;
break;
}
if (*input != '\0' && !strcmp(input, "YES")) {
result = 1;
break;
} else {
printf("Invalid input. Please type YES or hit CTRL+C to abort.\n");
continue;
}
}
return result;
}
static void (*update_progress_func)(struct progress_info_entry** list, int count) = NULL;
static double progress_granularity = 0.001;
void set_update_progress_func(void (*func)(struct progress_info_entry** list, int count))
{
update_progress_func = func;
}
void set_progress_granularity(double granularity)
{
progress_granularity = granularity;
}
mutex_t prog_mutex;
struct collection progress_info;
thread_once_t progress_info_once = THREAD_ONCE_INIT;
static void _init_progress_info(void)
{
mutex_init(&prog_mutex);
collection_init(&progress_info);
}
uint32_t progress_get_next_tag(void)
{
mutex_lock(&prog_mutex);
uint32_t newtag = ++progress_unique_tag;
mutex_unlock(&prog_mutex);
return newtag;
}
void progress_reset_tag(void)
{
progress_unique_tag = 1;
}
void register_progress(uint32_t tag, const char* label)
{
thread_once(&progress_info_once, _init_progress_info);
if (!label) {
return;
}
mutex_lock(&prog_mutex);
struct progress_info_entry* found = NULL;
FOREACH(struct progress_info_entry* e, &progress_info) {
if (e->tag == tag) {
found = e;
break;
}
} ENDFOREACH
if (found) {
if (strcmp(found->label, label) != 0) {
free(found->label);
found->label = strdup(label);
if (update_progress_func) {
update_progress_func((struct progress_info_entry**)(&progress_info)->list, progress_info.capacity);
} else {
print_progress_bar(found->label, found->progress);
}
}
mutex_unlock(&prog_mutex);
return;
}
struct progress_info_entry* newinfo = (struct progress_info_entry*)calloc(1, sizeof(struct progress_info_entry));
if (!newinfo) {
logger(LL_ERROR, "Out of memory?!\n");
exit(1);
}
newinfo->tag = tag;
newinfo->label = strdup(label);
newinfo->progress = 0;
collection_add(&progress_info, newinfo);
if (update_progress_func) {
update_progress_func((struct progress_info_entry**)(&progress_info)->list, progress_info.capacity);
} else {
print_progress_bar(newinfo->label, newinfo->progress);
}
mutex_unlock(&prog_mutex);
}
void finalize_progress(uint32_t tag)
{
mutex_lock(&prog_mutex);
struct progress_info_entry* found = NULL;
FOREACH(struct progress_info_entry* e, &progress_info) {
if (e->tag == tag) {
found = e;
break;
}
} ENDFOREACH
if (!found) {
mutex_unlock(&prog_mutex);
return;
}
collection_remove(&progress_info, found);
free(found->label);
free(found);
if (update_progress_func) {
update_progress_func((struct progress_info_entry**)(&progress_info)->list, progress_info.capacity);
}
mutex_unlock(&prog_mutex);
}
void print_progress_bar(const char* prefix, double progress)
{
int i = 0;
if (progress < 0) return;
if (progress > 1) progress = 1;
if (prefix) {
printf("\r%s [", prefix);
} else {
printf("\r[");
}
for (i = 0; i < 50; i++) {
if (i < (int)(progress*50.0)) printf("=");
else printf(" ");
}
printf("] %5.1f%% ", progress*100.0);
if (progress >= 1) printf("\n");
fflush(stdout);
}
void set_progress(uint32_t tag, double progress)
{
mutex_lock(&prog_mutex);
struct progress_info_entry* found = NULL;
FOREACH(struct progress_info_entry* e, &progress_info) {
if (e->tag == tag) {
found = e;
break;
}
} ENDFOREACH
if (!found) {
mutex_unlock(&prog_mutex);
return;
}
if (progress < 0) progress = 0;
if (progress > 1.0) progress = 1.0;
found->progress = progress;
if ((progress == 0) || (found->progress - found->lastprog >= progress_granularity)) {
if (update_progress_func) {
update_progress_func((struct progress_info_entry**)(&progress_info)->list, progress_info.capacity);
} else {
print_progress_bar(found->label, found->progress);
}
found->lastprog = found->progress;
}
mutex_unlock(&prog_mutex);
}
#define GET_RAND(min, max) ((rand() % (max - min)) + min)
@@ -485,17 +665,14 @@ char *get_temp_filename(const char *prefix)
void idevicerestore_progress(struct idevicerestore_client_t* client, int step, double progress)
{
thread_once(&init_once, _log_init);
mutex_lock(&log_mutex);
if(client && client->progress_cb) {
client->progress_cb(step, progress, client->progress_cb_data);
} else {
// we don't want to be too verbose in regular idevicerestore.
if ((step == RESTORE_STEP_UPLOAD_FS) || (step == RESTORE_STEP_VERIFY_FS) || (step == RESTORE_STEP_FLASH_FW) || (step == RESTORE_STEP_UPLOAD_IMG)) {
print_progress_bar(100.0 * progress);
print_progress_bar(NULL, progress);
}
}
mutex_unlock(&log_mutex);
}
#ifndef HAVE_STRSEP
+32 -8
View File
@@ -40,6 +40,7 @@ extern "C" {
#include <libimobiledevice-glue/thread.h>
#include "idevicerestore.h"
#include "log.h"
#define _MODE_UNKNOWN 0
#define _MODE_WTF 1
@@ -140,19 +141,42 @@ struct idevicerestore_client_t {
int async_err;
};
extern int global_quit_flag;
extern struct idevicerestore_mode_t idevicerestore_modes[];
extern int idevicerestore_debug;
__attribute__((format(printf, 1, 2)))
void info(const char* format, ...);
__attribute__((format(printf, 1, 2)))
void error(const char* format, ...);
__attribute__((format(printf, 1, 2)))
void debug(const char* format, ...);
void set_banner_funcs(void (*showfunc)(const char*), void (*hidefunc)(void));
void show_banner(const char* text);
void hide_banner();
struct progress_info_entry {
uint32_t tag;
char* label;
double progress;
int lastprog;
};
void set_update_progress_func(void (*func)(struct progress_info_entry** list, int count));
void set_progress_granularity(double granularity);
uint32_t progress_get_next_tag(void);
void progress_reset_tag(void);
void register_progress(uint32_t tag, const char* label);
void set_progress(uint32_t tag, double progress);
void finalize_progress(uint32_t tag);
void print_progress_bar(const char* prefix, double progress);
struct tuple {
int idx;
int len;
int plen;
};
int process_text_lines(const char* text, int maxwidth, struct tuple** lines_out, int* maxlen_out);
void set_prompt_func(int (*func)(const char* title, const char* text));
int prompt_user(const char* title, const char* message);
void debug_plist(plist_t plist);
void print_progress_bar(double progress);
int read_file(const char* filename, void** data, size_t* size);
int write_file(const char* filename, const void* data, size_t size);
+54 -56
View File
@@ -36,7 +36,7 @@
static int dfu_progress_callback(irecv_client_t client, const irecv_event_t* event) {
if (event->type == IRECV_PROGRESS) {
print_progress_bar(event->progress);
set_progress('DFUP', (double)event->progress/100.0);
}
return 0;
}
@@ -49,24 +49,26 @@ int dfu_client_new(struct idevicerestore_client_t* client)
client->dfu = (struct dfu_client_t*)malloc(sizeof(struct dfu_client_t));
memset(client->dfu, 0, sizeof(struct dfu_client_t));
if (client->dfu == NULL) {
error("ERROR: Out of memory\n");
logger(LL_ERROR, "Out of memory\n");
return -1;
}
}
if (irecv_open_with_ecid_and_attempts(&dfu, client->ecid, 10) != IRECV_E_SUCCESS) {
error("ERROR: Unable to connect to device in DFU mode\n");
logger(LL_ERROR, "Unable to connect to device in DFU mode\n");
return -1;
}
irecv_event_subscribe(dfu, IRECV_PROGRESS, &dfu_progress_callback, NULL);
client->dfu->client = dfu;
register_progress('DFUP', "Uploading");
return 0;
}
void dfu_client_free(struct idevicerestore_client_t* client)
{
if(client != NULL) {
finalize_progress('DFUP');
if (client->dfu != NULL) {
if(client->dfu->client != NULL) {
irecv_close(client->dfu->client);
@@ -107,11 +109,11 @@ int dfu_send_buffer_with_options(struct idevicerestore_client_t* client, unsigne
{
irecv_error_t err = 0;
info("Sending data (%d bytes)...\n", size);
logger(LL_INFO, "Sending data (%d bytes)...\n", size);
err = irecv_send_buffer(client->dfu->client, buffer, size, irecv_options);
if (err != IRECV_E_SUCCESS) {
error("ERROR: Unable to send data: %s\n", irecv_strerror(err));
logger(LL_ERROR, "Unable to send data: %s\n", irecv_strerror(err));
return -1;
}
@@ -144,19 +146,19 @@ int dfu_send_component(struct idevicerestore_client_t* client, plist_t build_ide
} else {
if (tss) {
if (tss_response_get_path_by_entry(tss, component, &path) < 0) {
debug("NOTE: No path for component %s in TSS, will fetch from build_identity\n", component);
logger(LL_DEBUG, "No path for component %s in TSS, will fetch from build_identity\n", component);
}
}
if (!path) {
if (build_identity_get_component_path(build_identity, component, &path) < 0) {
error("ERROR: Unable to get path for component '%s'\n", component);
logger(LL_ERROR, "Unable to get path for component '%s'\n", component);
free(path);
return -1;
}
}
if (extract_component(client->ipsw, path, &component_data, &component_size) < 0) {
error("ERROR: Unable to extract component: %s\n", component);
logger(LL_ERROR, "Unable to extract component: %s\n", component);
free(path);
return -1;
}
@@ -168,7 +170,7 @@ int dfu_send_component(struct idevicerestore_client_t* client, plist_t build_ide
uint32_t size = 0;
if (personalize_component(client, component, component_data, component_size, tss, &data, &size) < 0) {
error("ERROR: Unable to get personalized component: %s\n", component);
logger(LL_ERROR, "Unable to get personalized component: %s\n", component);
free(component_data);
return -1;
}
@@ -179,14 +181,14 @@ int dfu_send_component(struct idevicerestore_client_t* client, plist_t build_ide
unsigned char* ticket = NULL;
unsigned int tsize = 0;
if (tss_response_get_ap_ticket(client->tss, &ticket, &tsize) < 0) {
error("ERROR: Unable to get ApTicket from TSS request\n");
logger(LL_ERROR, "Unable to get ApTicket from TSS request\n");
return -1;
}
uint32_t fillsize = 0;
if (tsize % 64 != 0) {
fillsize = ((tsize / 64) + 1) * 64;
}
debug("ticket size = %d\nfillsize = %d\n", tsize, fillsize);
logger(LL_DEBUG, "ticket size = %d\nfillsize = %d\n", tsize, fillsize);
unsigned char* newdata = (unsigned char*)malloc(size + fillsize);
memcpy(newdata, ticket, tsize);
memset(newdata + tsize, '\xFF', fillsize - tsize);
@@ -196,11 +198,11 @@ int dfu_send_component(struct idevicerestore_client_t* client, plist_t build_ide
size += fillsize;
}
info("Sending %s (%d bytes)...\n", component, size);
logger(LL_INFO, "Sending %s (%d bytes)...\n", component, size);
irecv_error_t err = irecv_send_buffer(client->dfu->client, data, size, IRECV_SEND_OPT_DFU_NOTIFY_FINISH);
if (err != IRECV_E_SUCCESS) {
error("ERROR: Unable to send %s component: %s\n", component, irecv_strerror(err));
logger(LL_ERROR, "Unable to send %s component: %s\n", component, irecv_strerror(err));
free(data);
return -1;
}
@@ -366,14 +368,14 @@ int dfu_send_component_and_command(struct idevicerestore_client_t* client, plist
irecv_error_t dfu_error = IRECV_E_SUCCESS;
if (dfu_send_component(client, build_identity, component) < 0) {
error("ERROR: Unable to send %s to device.\n", component);
logger(LL_ERROR, "Unable to send %s to device.\n", component);
return -1;
}
info("INFO: executing command: %s\n", command);
logger(LL_INFO, "INFO: executing command: %s\n", command);
dfu_error = irecv_send_command(client->dfu->client, command);
if (dfu_error != IRECV_E_SUCCESS) {
error("ERROR: Unable to execute %s\n", command);
logger(LL_ERROR, "Unable to execute %s\n", command);
return -1;
}
@@ -384,10 +386,10 @@ int dfu_send_command(struct idevicerestore_client_t* client, const char* command
{
irecv_error_t dfu_error = IRECV_E_SUCCESS;
info("INFO: executing command: %s\n", command);
logger(LL_INFO, "INFO: executing command: %s\n", command);
dfu_error = irecv_send_command(client->dfu->client, command);
if (dfu_error != IRECV_E_SUCCESS) {
error("ERROR: Unable to execute %s\n", command);
logger(LL_ERROR, "Unable to execute %s\n", command);
return -1;
}
@@ -398,7 +400,7 @@ int dfu_send_iboot_stage1_components(struct idevicerestore_client_t* client, pli
{
plist_t manifest_node = plist_dict_get_item(build_identity, "Manifest");
if (!manifest_node || plist_get_node_type(manifest_node) != PLIST_DICT) {
error("ERROR: Unable to find manifest node\n");
logger(LL_ERROR, "Unable to find manifest node\n");
return -1;
}
@@ -422,12 +424,12 @@ int dfu_send_iboot_stage1_components(struct idevicerestore_client_t* client, pli
uint8_t b = 0;
plist_get_bool_val(iboot_node, &b);
if (b) {
debug("DEBUG: %s is loaded by iBoot Stage 1 and iBoot.\n", key);
logger(LL_DEBUG, "%s is loaded by iBoot Stage 1 and iBoot.\n", key);
} else {
debug("DEBUG: %s is loaded by iBoot Stage 1 but not iBoot...\n", key);
logger(LL_DEBUG, "%s is loaded by iBoot Stage 1 but not iBoot...\n", key);
}
if (dfu_send_component_and_command(client, build_identity, key, "firmware") < 0) {
error("ERROR: Unable to send component '%s' to device.\n", key);
logger(LL_ERROR, "Unable to send component '%s' to device.\n", key);
err++;
}
}
@@ -443,14 +445,14 @@ int dfu_enter_recovery(struct idevicerestore_client_t* client, plist_t build_ide
int mode = 0;
if (dfu_client_new(client) < 0) {
error("ERROR: Unable to connect to DFU device\n");
logger(LL_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");
logger(LL_NOTICE, "device is not in DFU mode, assuming recovery mode.\n");
client->mode = MODE_RECOVERY;
return 0;
}
@@ -458,7 +460,7 @@ int dfu_enter_recovery(struct idevicerestore_client_t* client, plist_t build_ide
mutex_lock(&client->device_event_mutex);
if (dfu_send_component(client, build_identity, "iBSS") < 0) {
error("ERROR: Unable to send iBSS to device\n");
logger(LL_ERROR, "Unable to send iBSS to device\n");
irecv_close(client->dfu->client);
client->dfu->client = NULL;
return -1;
@@ -467,21 +469,21 @@ int dfu_enter_recovery(struct idevicerestore_client_t* client, plist_t build_ide
if (client->build_major > 8) {
/* reconnect */
debug("Waiting for device to disconnect...\n");
logger(LL_DEBUG, "Waiting for device to disconnect...\n");
cond_wait_timeout(&client->device_event_cond, &client->device_event_mutex, 10000);
if (client->mode != MODE_UNKNOWN || (client->flags & FLAG_QUIT)) {
mutex_unlock(&client->device_event_mutex);
if (!(client->flags & FLAG_QUIT)) {
error("ERROR: Device did not disconnect. Possibly invalid iBSS. Reset device and try again.\n");
logger(LL_ERROR, "Device did not disconnect. Possibly invalid iBSS. Reset device and try again.\n");
}
return -1;
}
debug("Waiting for device to reconnect...\n");
logger(LL_DEBUG, "Waiting for device to reconnect...\n");
cond_wait_timeout(&client->device_event_cond, &client->device_event_mutex, 10000);
if ((client->mode != MODE_DFU && client->mode != MODE_RECOVERY) || (client->flags & FLAG_QUIT)) {
mutex_unlock(&client->device_event_mutex);
if (!(client->flags & FLAG_QUIT)) {
error("ERROR: Device did not reconnect in DFU or recovery mode. Possibly invalid iBSS. Reset device and try again.\n");
logger(LL_ERROR, "Device did not reconnect in DFU or recovery mode. Possibly invalid iBSS. Reset device and try again.\n");
}
return -1;
}
@@ -493,7 +495,7 @@ int dfu_enter_recovery(struct idevicerestore_client_t* client, plist_t build_ide
unsigned 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");
logger(LL_ERROR, "Unable to get ApNonce from device!\n");
return -1;
}
@@ -508,29 +510,25 @@ int dfu_enter_recovery(struct idevicerestore_client_t* client, plist_t build_ide
free(nonce);
}
info("Nonce: ");
int i;
for (i = 0; i < client->nonce_size; i++) {
info("%02x ", client->nonce[i]);
}
info("\n");
logger(LL_INFO, "Nonce: ");
logger_dump_hex(LL_INFO, client->nonce, client->nonce_size);
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");
logger(LL_ERROR, "Unable to get SHSH blobs for this device\n");
return -1;
}
if (!client->tss) {
error("ERROR: can't continue without TSS\n");
logger(LL_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");
logger(LL_ERROR, "set configuration failed\n");
}
mutex_lock(&client->device_event_mutex);
@@ -540,7 +538,7 @@ int dfu_enter_recovery(struct idevicerestore_client_t* client, plist_t build_ide
// Without this empty policy file & its special signature, iBEC won't start.
if (dfu_send_component_and_command(client, build_identity, "Ap,LocalPolicy", "lpolrestore") < 0) {
mutex_unlock(&client->device_event_mutex);
error("ERROR: Unable to send Ap,LocalPolicy to device\n");
logger(LL_ERROR, "Unable to send Ap,LocalPolicy to device\n");
irecv_close(client->dfu->client);
client->dfu->client = NULL;
return -1;
@@ -553,17 +551,17 @@ int dfu_enter_recovery(struct idevicerestore_client_t* client, plist_t build_ide
boot_stage = strtoul(value, NULL, 0);
}
if (boot_stage > 0) {
info("iBoot boot-stage=%s\n", value);
logger(LL_INFO, "iBoot boot-stage=%s\n", value);
free(value);
value = NULL;
if (boot_stage != 1) {
error("ERROR: iBoot should be at boot stage 1, continuing anyway...\n");
logger(LL_ERROR, "iBoot should be at boot stage 1, continuing anyway...\n");
}
}
if (dfu_send_iboot_stage1_components(client, build_identity) < 0) {
mutex_unlock(&client->device_event_mutex);
error("ERROR: Unable to send iBoot stage 1 components to device\n");
logger(LL_ERROR, "Unable to send iBoot stage 1 components to device\n");
irecv_close(client->dfu->client);
client->dfu->client = NULL;
return -1;
@@ -571,7 +569,7 @@ int dfu_enter_recovery(struct idevicerestore_client_t* client, plist_t build_ide
if (dfu_send_command(client, "setenv auto-boot false") < 0) {
mutex_unlock(&client->device_event_mutex);
error("ERROR: Unable to send command to device\n");
logger(LL_ERROR, "Unable to send command to device\n");
irecv_close(client->dfu->client);
client->dfu->client = NULL;
return -1;
@@ -579,7 +577,7 @@ int dfu_enter_recovery(struct idevicerestore_client_t* client, plist_t build_ide
if (dfu_send_command(client, "saveenv") < 0) {
mutex_unlock(&client->device_event_mutex);
error("ERROR: Unable to send command to device\n");
logger(LL_ERROR, "Unable to send command to device\n");
irecv_close(client->dfu->client);
client->dfu->client = NULL;
return -1;
@@ -587,7 +585,7 @@ int dfu_enter_recovery(struct idevicerestore_client_t* client, plist_t build_ide
if (dfu_send_command(client, "setenvnp boot-args rd=md0 nand-enable-reformat=1 -progress -restore") < 0) {
mutex_unlock(&client->device_event_mutex);
error("ERROR: Unable to send command to device\n");
logger(LL_ERROR, "Unable to send command to device\n");
irecv_close(client->dfu->client);
client->dfu->client = NULL;
return -1;
@@ -595,7 +593,7 @@ int dfu_enter_recovery(struct idevicerestore_client_t* client, plist_t build_ide
if (dfu_send_component(client, build_identity, "RestoreLogo") < 0) {
mutex_unlock(&client->device_event_mutex);
error("ERROR: Unable to send RestoreDCP to device\n");
logger(LL_ERROR, "Unable to send RestoreDCP to device\n");
irecv_close(client->dfu->client);
client->dfu->client = NULL;
return -1;
@@ -603,7 +601,7 @@ int dfu_enter_recovery(struct idevicerestore_client_t* client, plist_t build_ide
if (dfu_send_command(client, "setpicture 4") < 0) {
mutex_unlock(&client->device_event_mutex);
error("ERROR: Unable to send command to device\n");
logger(LL_ERROR, "Unable to send command to device\n");
irecv_close(client->dfu->client);
client->dfu->client = NULL;
return -1;
@@ -611,7 +609,7 @@ int dfu_enter_recovery(struct idevicerestore_client_t* client, plist_t build_ide
if (dfu_send_command(client, "bgcolor 0 0 0") < 0) {
mutex_unlock(&client->device_event_mutex);
error("ERROR: Unable to send command to device\n");
logger(LL_ERROR, "Unable to send command to device\n");
irecv_close(client->dfu->client);
client->dfu->client = NULL;
return -1;
@@ -621,7 +619,7 @@ int dfu_enter_recovery(struct idevicerestore_client_t* client, plist_t build_ide
/* send iBEC */
if (dfu_send_component(client, build_identity, "iBEC") < 0) {
mutex_unlock(&client->device_event_mutex);
error("ERROR: Unable to send iBEC to device\n");
logger(LL_ERROR, "Unable to send iBEC to device\n");
irecv_close(client->dfu->client);
client->dfu->client = NULL;
return -1;
@@ -631,7 +629,7 @@ int dfu_enter_recovery(struct idevicerestore_client_t* client, plist_t build_ide
sleep(1);
if (irecv_send_command_breq(client->dfu->client, "go", 1) != IRECV_E_SUCCESS) {
mutex_unlock(&client->device_event_mutex);
error("ERROR: Unable to execute iBEC\n");
logger(LL_ERROR, "Unable to execute iBEC\n");
return -1;
}
@@ -642,28 +640,28 @@ int dfu_enter_recovery(struct idevicerestore_client_t* client, plist_t build_ide
dfu_client_free(client);
}
debug("Waiting for device to disconnect...\n");
logger(LL_DEBUG, "Waiting for device to disconnect...\n");
cond_wait_timeout(&client->device_event_cond, &client->device_event_mutex, 10000);
if (client->mode != MODE_UNKNOWN || (client->flags & FLAG_QUIT)) {
mutex_unlock(&client->device_event_mutex);
if (!(client->flags & FLAG_QUIT)) {
error("ERROR: Device did not disconnect. Possibly invalid %s. Reset device and try again.\n", (client->build_major > 8) ? "iBEC" : "iBSS");
logger(LL_ERROR, "Device did not disconnect. Possibly invalid %s. Reset device and try again.\n", (client->build_major > 8) ? "iBEC" : "iBSS");
}
return -1;
}
debug("Waiting for device to reconnect in recovery mode...\n");
logger(LL_DEBUG, "Waiting for device to reconnect in recovery mode...\n");
cond_wait_timeout(&client->device_event_cond, &client->device_event_mutex, 10000);
if (client->mode != MODE_RECOVERY || (client->flags & FLAG_QUIT)) {
mutex_unlock(&client->device_event_mutex);
if (!(client->flags & FLAG_QUIT)) {
error("ERROR: Device did not reconnect in recovery mode. Possibly invalid %s. Reset device and try again.\n", (client->build_major > 8) ? "iBEC" : "iBSS");
logger(LL_ERROR, "Device did not reconnect in recovery mode. Possibly invalid %s. Reset device and try again.\n", (client->build_major > 8) ? "iBEC" : "iBSS");
}
return -1;
}
mutex_unlock(&client->device_event_mutex);
if (recovery_client_new(client) < 0) {
error("ERROR: Unable to connect to recovery device\n");
logger(LL_ERROR, "Unable to connect to recovery device\n");
if (client->recovery->client) {
irecv_close(client->recovery->client);
client->recovery->client = NULL;
+21 -16
View File
@@ -48,7 +48,7 @@ int download_to_buffer(const char* url, char** buf, uint32_t* length)
int res = 0;
CURL* handle = curl_easy_init();
if (handle == NULL) {
error("ERROR: could not initialize CURL\n");
logger(LL_ERROR, "could not initialize CURL\n");
return -1;
}
@@ -57,7 +57,7 @@ int download_to_buffer(const char* url, char** buf, uint32_t* length)
response.content = malloc(1);
response.content[0] = '\0';
if (idevicerestore_debug)
if (log_level >= LL_DEBUG)
curl_easy_setopt(handle, CURLOPT_VERBOSE, 1);
/* disable SSL verification to allow download from untrusted https locations */
@@ -86,17 +86,14 @@ int download_to_buffer(const char* url, char** buf, uint32_t* length)
return res;
}
static int lastprogress = 0;
static int download_progress(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow)
{
double p = (dlnow / dltotal) * 100;
double p = (dlnow / dltotal);
if (p < 100.0) {
if ((int)p > lastprogress) {
info("downloading: %d%%\n", (int)p);
lastprogress = (int)p;
}
set_progress('DNLD', p);
if (global_quit_flag > 0) {
return 1;
}
return 0;
@@ -107,19 +104,17 @@ int download_to_file(const char* url, const char* filename, int enable_progress)
int res = 0;
CURL* handle = curl_easy_init();
if (handle == NULL) {
error("ERROR: could not initialize CURL\n");
logger(LL_ERROR, "Could not initialize CURL\n");
return -1;
}
FILE* f = fopen(filename, "wb");
if (!f) {
error("ERROR: cannot open '%s' for writing\n", filename);
logger(LL_ERROR, "Cannot open '%s' for writing\n", filename);
return -1;
}
lastprogress = 0;
if (idevicerestore_debug)
if (log_level >= LL_DEBUG)
curl_easy_setopt(handle, CURLOPT_VERBOSE, 1);
/* disable SSL verification to allow download from untrusted https locations */
@@ -128,8 +123,10 @@ int download_to_file(const char* url, const char* filename, int enable_progress)
curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, NULL);
curl_easy_setopt(handle, CURLOPT_WRITEDATA, f);
if (enable_progress > 0)
if (enable_progress > 0) {
register_progress('DNLD', "Downloading");
curl_easy_setopt(handle, CURLOPT_PROGRESSFUNCTION, (curl_progress_callback)&download_progress);
}
curl_easy_setopt(handle, CURLOPT_NOPROGRESS, enable_progress > 0 ? 0: 1);
curl_easy_setopt(handle, CURLOPT_USERAGENT, USER_AGENT_STRING);
@@ -137,6 +134,11 @@ int download_to_file(const char* url, const char* filename, int enable_progress)
curl_easy_setopt(handle, CURLOPT_URL, url);
curl_easy_perform(handle);
if (enable_progress) {
finalize_progress('DNLD');
}
curl_easy_cleanup(handle);
#ifdef WIN32
@@ -151,6 +153,9 @@ int download_to_file(const char* url, const char* filename, int enable_progress)
res = -1;
remove(filename);
}
if (global_quit_flag > 0) {
res = -2;
}
return res;
}
+64 -66
View File
@@ -66,7 +66,7 @@ int fdr_connect(idevice_t device, fdr_type_t type, fdr_client_t* fdr)
*fdr = NULL;
debug("Connecting to FDR client at port %u\n", port);
logger(LL_DEBUG, "Connecting to FDR client at port %u\n", port);
for (i = 1; i <= attempts; i++) {
device_error = idevice_connect(device, port, &connection);
@@ -75,17 +75,17 @@ int fdr_connect(idevice_t device, fdr_type_t type, fdr_client_t* fdr)
}
if (i >= attempts) {
error("ERROR: Unable to connect to FDR client (%d)\n", device_error);
logger(LL_ERROR, "Unable to connect to FDR client (%d)\n", device_error);
return -1;
}
sleep(2);
debug("Retrying connection...\n");
logger(LL_DEBUG, "Retrying connection...\n");
}
fdr_client_t fdr_loc = calloc(1, sizeof(struct fdr_client));
if (!fdr_loc) {
error("ERROR: Unable to allocate memory\n");
logger(LL_ERROR, "Unable to allocate memory\n");
return -1;
}
fdr_loc->connection = connection;
@@ -138,7 +138,7 @@ int fdr_poll_and_handle_message(fdr_client_t fdr)
uint16_t cmd;
if (!fdr) {
error("ERROR: Invalid FDR client\n");
logger(LL_ERROR, "Invalid FDR client\n");
return -1;
}
@@ -149,32 +149,32 @@ int fdr_poll_and_handle_message(fdr_client_t fdr)
if (device_error == IDEVICE_E_SUCCESS && bytes != sizeof(cmd))
#endif
{
debug("FDR %p timeout waiting for command\n", fdr);
logger(LL_DEBUG, "FDR %p timeout waiting for command\n", fdr);
return 0;
}
else if (device_error != IDEVICE_E_SUCCESS) {
if (fdr->connection) {
error("ERROR: Unable to receive message from FDR %p (%d). %u/%u bytes\n", fdr, device_error, bytes, (uint32_t)sizeof(cmd));
logger(LL_ERROR, "Unable to receive message from FDR %p (%d). %u/%u bytes\n", fdr, device_error, bytes, (uint32_t)sizeof(cmd));
}
return -1;
}
if (cmd == FDR_SYNC_MSG) {
debug("FDR %p got sync message\n", fdr);
logger(LL_DEBUG, "FDR %p got sync message\n", fdr);
return fdr_handle_sync_cmd(fdr);
}
if (cmd == FDR_PROXY_MSG) {
debug("FDR %p got proxy message\n", fdr);
logger(LL_DEBUG, "FDR %p got proxy message\n", fdr);
return fdr_handle_proxy_cmd(fdr);
}
if (cmd == FDR_PLIST_MSG) {
debug("FDR %p got plist message\n", fdr);
logger(LL_DEBUG, "FDR %p got plist message\n", fdr);
return fdr_handle_plist_cmd(fdr);
}
error("WARNING: FDR %p received unknown packet %#x of size %u\n", fdr, cmd, bytes);
logger(LL_WARNING, "FDR %p received unknown packet %#x of size %u\n", fdr, cmd, bytes);
return 0;
}
@@ -184,14 +184,14 @@ void *fdr_listener_thread(void *cdata)
int res;
while (fdr && fdr->connection) {
debug("FDR %p waiting for message...\n", fdr);
logger(LL_DEBUG, "FDR %p waiting for message...\n", fdr);
res = fdr_poll_and_handle_message(fdr);
if (fdr->type == FDR_CTRL && res >= 0)
continue; // main thread should always retry
if (res != 0)
break;
}
debug("FDR %p terminating...\n", fdr);
logger(LL_DEBUG, "FDR %p terminating...\n", fdr);
fdr_free(fdr);
return (void *)(intptr_t)res;
}
@@ -204,26 +204,26 @@ static int fdr_receive_plist(fdr_client_t fdr, plist_t* data)
device_error = idevice_connection_receive(fdr->connection, (char*)&len, sizeof(len), &bytes);
if (device_error != IDEVICE_E_SUCCESS) {
error("ERROR: Unable to receive packet length from FDR (%d)\n", device_error);
logger(LL_ERROR, "Unable to receive packet length from FDR (%d)\n", device_error);
return -1;
}
buf = calloc(1, len);
if (!buf) {
error("ERROR: Unable to allocate memory for FDR receive buffer\n");
logger(LL_ERROR, "Unable to allocate memory for FDR receive buffer\n");
return -1;
}
device_error = idevice_connection_receive(fdr->connection, buf, len, &bytes);
if (device_error != IDEVICE_E_SUCCESS) {
error("ERROR: Unable to receive data from FDR\n");
logger(LL_ERROR, "Unable to receive data from FDR\n");
free(buf);
return -1;
}
plist_from_bin(buf, bytes, data);
free(buf);
debug("FDR Received %d bytes\n", bytes);
logger(LL_DEBUG, "FDR Received %d bytes\n", bytes);
return 0;
}
@@ -241,12 +241,11 @@ static int fdr_send_plist(fdr_client_t fdr, plist_t data)
if (!buf)
return -1;
debug("FDR sending %d bytes:\n", len);
if (idevicerestore_debug)
debug_plist(data);
logger(LL_DEBUG, "FDR sending %d bytes:\n", len);
logger_dump_plist(LL_DEBUG, data, 1);
device_error = idevice_connection_send(fdr->connection, (char *)&len, sizeof(len), &bytes);
if (device_error != IDEVICE_E_SUCCESS || bytes != sizeof(len)) {
error("ERROR: FDR unable to send data length. (%d) Sent %u of %u bytes.\n",
logger(LL_ERROR, "FDR unable to send data length. (%d) Sent %u of %u bytes.\n",
device_error, bytes, (uint32_t)sizeof(len));
free(buf);
return -1;
@@ -254,12 +253,12 @@ static int fdr_send_plist(fdr_client_t fdr, plist_t data)
device_error = idevice_connection_send(fdr->connection, buf, len, &bytes);
free(buf);
if (device_error != IDEVICE_E_SUCCESS || bytes != len) {
error("ERROR: FDR unable to send data (%d). Sent %u of %u bytes.\n",
logger(LL_ERROR, "FDR unable to send data (%d). Sent %u of %u bytes.\n",
device_error, bytes, len);
return -1;
}
debug("FDR Sent %d bytes\n", bytes);
logger(LL_DEBUG, "FDR Sent %d bytes\n", bytes);
return 0;
}
@@ -270,18 +269,18 @@ static int fdr_ctrl_handshake(fdr_client_t fdr)
plist_t dict, node;
int res;
debug("About to do ctrl handshake\n");
logger(LL_DEBUG, "About to do ctrl handshake\n");
ctrlprotoversion = 2;
device_error = idevice_connection_send(fdr->connection, CTRLCMD, len, &bytes);
if (device_error != IDEVICE_E_SUCCESS || bytes != len) {
debug("Hmm... looks like the device doesn't like the newer protocol, using the old one\n");
logger(LL_DEBUG, "Hmm... looks like the device doesn't like the newer protocol, using the old one\n");
ctrlprotoversion = 1;
len = sizeof(HELLOCTRLCMD);
device_error = idevice_connection_send(fdr->connection, HELLOCTRLCMD, len, &bytes);
if (device_error != IDEVICE_E_SUCCESS || bytes != len) {
error("ERROR: FDR unable to send BeginCtrl. Sent %u of %u bytes.\n", bytes, len);
logger(LL_ERROR, "FDR unable to send BeginCtrl. Sent %u of %u bytes.\n", bytes, len);
return -1;
}
}
@@ -293,21 +292,20 @@ static int fdr_ctrl_handshake(fdr_client_t fdr)
res = fdr_send_plist(fdr, dict);
plist_free(dict);
if (res) {
error("ERROR: FDR could not send Begin command.\n");
logger(LL_ERROR, "FDR could not send Begin command.\n");
return -1;
}
if (fdr_receive_plist(fdr, &dict)) {
error("ERROR: FDR did not get Begin command reply.\n");
logger(LL_ERROR, "FDR did not get Begin command reply.\n");
return -1;
}
if (idevicerestore_debug)
debug_plist(dict);
logger_dump_plist(LL_DEBUG, dict, 1);
node = plist_dict_get_item(dict, "ConnPort");
if (node && plist_get_node_type(node) == PLIST_UINT) {
plist_get_uint_val(node, &conn_port);
} else {
error("ERROR: Could not get FDR ConnPort value\n");
logger(LL_ERROR, "Could not get FDR ConnPort value\n");
return -1;
}
@@ -321,26 +319,26 @@ static int fdr_ctrl_handshake(fdr_client_t fdr)
bytes = 0;
device_error = idevice_connection_receive(fdr->connection, buf, 10, &bytes);
if (device_error != IDEVICE_E_SUCCESS) {
error("ERROR: Could not receive reply to HelloCtrl command\n");
logger(LL_ERROR, "Could not receive reply to HelloCtrl command\n");
return -1;
}
if (memcmp(buf, "HelloCtrl", 10) != 0) {
buf[9] = '\0';
error("ERROR: Did not receive HelloCtrl as reply, but %s\n", buf);
logger(LL_ERROR, "Did not receive HelloCtrl as reply, but %s\n", buf);
return -1;
}
bytes = 0;
device_error = idevice_connection_receive(fdr->connection, (char*)&cport, 2, &bytes);
if (device_error != IDEVICE_E_SUCCESS) {
error("ERROR: Failed to receive conn port\n");
logger(LL_ERROR, "Failed to receive conn port\n");
return -1;
}
conn_port = le16toh(cport);
}
debug("Ctrl handshake done (ConnPort = %" PRIu64 ")\n", (uint64_t)conn_port);
logger(LL_DEBUG, "Ctrl handshake done (ConnPort = %" PRIu64 ")\n", (uint64_t)conn_port);
return 0;
}
@@ -353,13 +351,13 @@ static int fdr_sync_handshake(fdr_client_t fdr)
device_error = idevice_connection_send(fdr->connection, HELLOCMD, len, &bytes);
if (device_error != IDEVICE_E_SUCCESS || bytes != len) {
error("ERROR: FDR unable to send Hello. Sent %u of %u bytes.\n", bytes, len);
logger(LL_ERROR, "FDR unable to send Hello. Sent %u of %u bytes.\n", bytes, len);
return -1;
}
if (ctrlprotoversion == 2) {
if (fdr_receive_plist(fdr, &reply)) {
error("ERROR: FDR did not get HelloConn reply.\n");
logger(LL_ERROR, "FDR did not get HelloConn reply.\n");
return -1;
}
char* identifier = NULL;
@@ -382,13 +380,13 @@ static int fdr_sync_handshake(fdr_client_t fdr)
if (identifier) {
free(identifier);
}
error("ERROR: Did not receive HelloConn reply...\n");
logger(LL_ERROR, "Did not receive HelloConn reply...\n");
return -1;
}
free(cmd);
if (identifier) {
debug("Got device identifier %s\n", identifier);
logger(LL_DEBUG, "Got device identifier %s\n", identifier);
free(identifier);
}
@@ -398,12 +396,12 @@ static int fdr_sync_handshake(fdr_client_t fdr)
bytes = 0;
device_error = idevice_connection_receive(fdr->connection, buf, 10, &bytes);
if (device_error != IDEVICE_E_SUCCESS) {
error("ERROR: Could not receive reply to HelloConn command\n");
logger(LL_ERROR, "Could not receive reply to HelloConn command\n");
return -1;
}
if (memcmp(buf, "HelloConn", 10) != 0) {
buf[9] = '\0';
error("ERROR: Did not receive HelloConn as reply, but %s\n", buf);
logger(LL_ERROR, "Did not receive HelloConn as reply, but %s\n", buf);
return -1;
}
}
@@ -422,18 +420,18 @@ static int fdr_handle_sync_cmd(fdr_client_t fdr_ctrl)
device_error = idevice_connection_receive(fdr_ctrl->connection, buf, sizeof(buf), &bytes);
if (device_error != IDEVICE_E_SUCCESS || bytes != 2) {
error("ERROR: Unexpected data from FDR\n");
logger(LL_ERROR, "Unexpected data from FDR\n");
return -1;
}
/* Open a new connection and wait for messages on it */
if (fdr_connect(fdr_ctrl->device, FDR_CONN, &fdr)) {
error("ERROR: Failed to connect to FDR port\n");
logger(LL_ERROR, "Failed to connect to FDR port\n");
return -1;
}
debug("FDR connected in reply to sync message, starting command thread\n");
logger(LL_DEBUG, "FDR connected in reply to sync message, starting command thread\n");
res = thread_new(&fdr_thread, fdr_listener_thread, fdr);
if(res) {
error("ERROR: Failed to start FDR command thread\n");
logger(LL_ERROR, "Failed to start FDR command thread\n");
fdr_free(fdr);
}
return res;
@@ -445,12 +443,12 @@ static int fdr_handle_plist_cmd(fdr_client_t fdr)
plist_t dict;
if (fdr_receive_plist(fdr, &dict)) {
error("ERROR: FDR %p could not receive plist command.\n", fdr);
logger(LL_ERROR, "FDR %p could not receive plist command.\n", fdr);
return -1;
}
plist_t node = plist_dict_get_item(dict, "Command");
if (!node || (plist_get_node_type(node) != PLIST_STRING)) {
error("ERROR: FDR %p Could not find Command in plist command\n", fdr);
logger(LL_ERROR, "FDR %p Could not find Command in plist command\n", fdr);
plist_free(dict);
return -1;
}
@@ -459,7 +457,7 @@ static int fdr_handle_plist_cmd(fdr_client_t fdr)
plist_free(dict);
if (!command) {
info("FDR %p received empty plist command\n", fdr);
logger(LL_INFO, "FDR %p received empty plist command\n", fdr);
return -1;
}
@@ -469,12 +467,12 @@ static int fdr_handle_plist_cmd(fdr_client_t fdr)
res = fdr_send_plist(fdr, dict);
plist_free(dict);
if (res) {
error("ERROR: FDR %p could not send Ping command reply.\n", fdr);
logger(LL_ERROR, "FDR %p could not send Ping command reply.\n", fdr);
free(command);
return -1;
}
} else {
error("WARNING: FDR %p received unknown plist command: %s\n", fdr, command);
logger(LL_WARNING, "FDR %p received unknown plist command: %s\n", fdr, command);
free(command);
return -1;
}
@@ -495,17 +493,17 @@ static int fdr_handle_proxy_cmd(fdr_client_t fdr)
buf = malloc(bufsize);
if (!buf) {
error("ERROR: %s: malloc failed\n", __func__);
logger(LL_ERROR, "%s: malloc failed\n", __func__);
return -1;
}
device_error = idevice_connection_receive(fdr->connection, buf, bufsize, &bytes);
if (device_error != IDEVICE_E_SUCCESS) {
free(buf);
error("ERROR: FDR %p failed to read data for proxy command\n", fdr);
logger(LL_ERROR, "FDR %p failed to read data for proxy command\n", fdr);
return -1;
}
debug("Got proxy command with %u bytes\n", bytes);
logger(LL_DEBUG, "Got proxy command with %u bytes\n", bytes);
/* Just return success here unconditionally because we don't know
* anything else and we will eventually abort on failure anyway */
@@ -513,13 +511,13 @@ static int fdr_handle_proxy_cmd(fdr_client_t fdr)
device_error = idevice_connection_send(fdr->connection, (char *)&ack, sizeof(ack), &sent);
if (device_error != IDEVICE_E_SUCCESS || sent != sizeof(ack)) {
free(buf);
error("ERROR: FDR %p unable to send ack. Sent %u of %u bytes.\n",
logger(LL_ERROR, "FDR %p unable to send ack. Sent %u of %u bytes.\n",
fdr, sent, (uint32_t)sizeof(ack));
return -1;
}
if (bytes < 3) {
debug("FDR %p proxy command data too short, retrying\n", fdr);
logger(LL_DEBUG, "FDR %p proxy command data too short, retrying\n", fdr);
return fdr_poll_and_handle_message(fdr);
}
@@ -527,7 +525,7 @@ static int fdr_handle_proxy_cmd(fdr_client_t fdr)
device_error = idevice_connection_send(fdr->connection, buf, bytes, &sent);
if (device_error != IDEVICE_E_SUCCESS || sent != bytes) {
free(buf);
error("ERROR: FDR %p unable to send data. Sent %u of %u bytes.\n",
logger(LL_ERROR, "FDR %p unable to send data. Sent %u of %u bytes.\n",
fdr, sent, bytes);
return -1;
}
@@ -539,7 +537,7 @@ static int fdr_handle_proxy_cmd(fdr_client_t fdr)
port = be16toh(*p);
buf[bytes - 2] = '\0';
host = strdup(&buf[3]);
debug("FDR %p Proxy connect request to %s:%u\n", fdr, host, port);
logger(LL_DEBUG, "FDR %p Proxy connect request to %s:%u\n", fdr, host, port);
}
if (!host || !buf[2]) {
@@ -553,7 +551,7 @@ static int fdr_handle_proxy_cmd(fdr_client_t fdr)
free(host);
if (sockfd < 0) {
free(buf);
error("ERROR: Failed to connect socket: %s\n", strerror(errno));
logger(LL_ERROR, "Failed to connect socket: %s\n", strerror(errno));
return -1;
}
@@ -567,16 +565,16 @@ static int fdr_handle_proxy_cmd(fdr_client_t fdr)
if (device_error == IDEVICE_E_SUCCESS && !bytes)
#endif
{
//debug("WARNING: Timeout waiting for proxy payload. %p\n", fdr);
//logger(LL_DEBUG, "Timeout waiting for proxy payload. %p\n", fdr);
}
else if (device_error != IDEVICE_E_SUCCESS) {
error("ERROR: FDR %p Unable to receive proxy payload (%d)\n", fdr, device_error);
logger(LL_ERROR, "FDR %p Unable to receive proxy payload (%d)\n", fdr, device_error);
res = -1;
break;
}
if (bytes) {
debug("FDR %p got payload of %u bytes, now trying to proxy it\n", fdr, bytes);
debug("Sending %u bytes of data\n", bytes);
logger(LL_DEBUG, "FDR %p got payload of %u bytes, now trying to proxy it\n", fdr, bytes);
logger(LL_DEBUG, "Sending %u bytes of data\n", bytes);
sent = 0;
while (sent < bytes) {
int s = socket_send(sockfd, buf + sent, bytes - sent);
@@ -586,7 +584,7 @@ static int fdr_handle_proxy_cmd(fdr_client_t fdr)
sent += s;
}
if (sent != bytes) {
error("ERROR: Sending proxy payload failed: %s. Sent %u of %u bytes. \n", strerror(errno), sent, bytes);
logger(LL_ERROR, "Sending proxy payload failed: %s. Sent %u of %u bytes. \n", strerror(errno), sent, bytes);
socket_close(sockfd);
res = -1;
break;
@@ -599,14 +597,14 @@ static int fdr_handle_proxy_cmd(fdr_client_t fdr)
res = 1;
break;
} else if (bytes_ret < 0) {
error("ERROR: FDR %p receiving proxy payload failed: %d (%s)\n",
logger(LL_ERROR, "FDR %p receiving proxy payload failed: %d (%s)\n",
fdr, bytes_ret, strerror(-bytes_ret));
break;
}
bytes = bytes_ret;
if (bytes) {
debug("FDR %p Received %u bytes reply data,%s sending to device\n",
logger(LL_DEBUG, "FDR %p Received %u bytes reply data,%s sending to device\n",
fdr, bytes, (bytes ? "" : " not"));
sent = 0;
@@ -619,7 +617,7 @@ static int fdr_handle_proxy_cmd(fdr_client_t fdr)
sent += s;
}
if (device_error != IDEVICE_E_SUCCESS || bytes != sent) {
error("ERROR: FDR %p unable to send data (%d). Sent %u of %u bytes.\n", fdr, device_error, sent, bytes);
logger(LL_ERROR, "FDR %p unable to send data (%d). Sent %u of %u bytes.\n", fdr, device_error, sent, bytes);
res = -1;
break;
}
+9 -9
View File
@@ -96,7 +96,7 @@ static void fls_parse_elements(fls_file* fls)
offset += cur->size;
} while (offset < fls->size);
if (offset != fls->size) {
error("ERROR: %s: error parsing elements\n", __func__);
logger(LL_ERROR, "%s: error parsing elements\n", __func__);
return;
}
}
@@ -136,22 +136,22 @@ int fls_update_sig_blob(fls_file* fls, const unsigned char* sigdata, unsigned in
{
/* FIXME: the code in this function is not big endian safe */
if (!fls || !fls->num_elements) {
error("ERROR: %s: no data\n", __func__);
logger(LL_ERROR, "%s: no data\n", __func__);
return -1;
}
if (!fls->c_element) {
error("ERROR: %s: no fls_0c_element in fls data\n", __func__);
logger(LL_ERROR, "%s: no fls_0c_element in fls data\n", __func__);
return -1;
}
uint32_t datasize = *(uint32_t*)(fls->c_element->data + 0x10);
if (datasize != fls->c_element->data_size) {
error("ERROR: %s: data size mismatch (0x%x != 0x%x)\n", __func__, datasize, fls->c_element->data_size);
logger(LL_ERROR, "%s: data size mismatch (0x%x != 0x%x)\n", __func__, datasize, fls->c_element->data_size);
return -1;
}
uint32_t sigoffset = *(uint32_t*)(fls->c_element->data + 0x14);
if (sigoffset > datasize) {
error("ERROR: %s: signature offset greater than data size (0x%x > 0x%x)\n", __func__, sigoffset, datasize);
logger(LL_ERROR, "%s: signature offset greater than data size (0x%x > 0x%x)\n", __func__, sigoffset, datasize);
return -1;
}
@@ -162,7 +162,7 @@ int fls_update_sig_blob(fls_file* fls, const unsigned char* sigdata, unsigned in
uint32_t offset = 0;
void* newdata = malloc(newsize);
if (!newdata) {
error("ERROR: %s: out of memory\n", __func__);
logger(LL_ERROR, "%s: out of memory\n", __func__);
return -1;
}
uint32_t hdrsize = 0;
@@ -243,11 +243,11 @@ int fls_insert_ticket(fls_file* fls, const unsigned char* data, unsigned int siz
{
/* FIXME: the code in this function is not big endian safe */
if (!fls || !fls->num_elements) {
error("ERROR: %s: no data\n", __func__);
logger(LL_ERROR, "%s: no data\n", __func__);
return -1;
}
if (!fls->c_element) {
error("ERROR: %s: no fls_0c_element in fls data\n", __func__);
logger(LL_ERROR, "%s: no fls_0c_element in fls data\n", __func__);
return -1;
}
@@ -260,7 +260,7 @@ int fls_insert_ticket(fls_file* fls, const unsigned char* data, unsigned int siz
uint32_t offset = 0;
void* newdata = malloc(newsize);
if (!newdata) {
error("ERROR: %s: out of memory\n", __func__);
logger(LL_ERROR, "%s: out of memory\n", __func__);
return -1;
}
uint32_t hdrsize = 0;
+5 -5
View File
@@ -35,13 +35,13 @@ int ftab_parse(unsigned char *data, unsigned int data_size, ftab_t *ftab, uint32
}
if (data_size < sizeof(struct ftab_header)) {
error("ERROR: %s: Buffer too small for ftab data\n", __func__);
logger(LL_ERROR, "%s: Buffer too small for ftab data\n", __func__);
return -1;
}
struct ftab_header *hdr_ptr = (struct ftab_header*)data;
if (be32toh(hdr_ptr->magic) != 'ftab') {
error("ERROR: %s: Unexpected magic value 0x%08x\n", __func__, le32toh(hdr_ptr->magic));
logger(LL_ERROR, "%s: Unexpected magic value 0x%08x\n", __func__, le32toh(hdr_ptr->magic));
return -1;
}
@@ -108,13 +108,13 @@ int ftab_add_entry(ftab_t ftab, uint32_t tag, unsigned char *data, unsigned int
uint32_t new_index = ftab->header.num_entries;
struct ftab_entry *new_entries = realloc(ftab->entries, sizeof(struct ftab_entry) * (ftab->header.num_entries + 1));
if (!new_entries) {
error("ERROR: %s: realloc failed!\n", __func__);
logger(LL_ERROR, "%s: realloc failed!\n", __func__);
return -1;
}
ftab->entries = new_entries;
unsigned char **new_storage = realloc(ftab->storage, sizeof(unsigned char*) * (ftab->header.num_entries + 1));
if (!new_storage) {
error("ERROR: %s: realloc failed!\n", __func__);
logger(LL_ERROR, "%s: realloc failed!\n", __func__);
return -1;
}
ftab->storage = new_storage;
@@ -151,7 +151,7 @@ int ftab_write(ftab_t ftab, unsigned char **data, unsigned int *data_size)
unsigned char *data_out = (unsigned char*)malloc(total_size);
if (!data_out) {
error("ERROR: %s: Out of memory?!\n", __func__);
logger(LL_ERROR, "%s: Out of memory?!\n", __func__);
return -1;
}
+344 -292
View File
File diff suppressed because it is too large Load Diff
+1 -3
View File
@@ -46,6 +46,7 @@ extern "C" {
#define FLAG_ALLOW_RESTORE_MODE (1 << 10)
#define FLAG_NO_RESTORE (1 << 11)
#define FLAG_IGNORE_ERRORS (1 << 12)
#define FLAG_IN_PROGRESS (1 << 30)
#define RESTORE_VARIANT_ERASE_INSTALL "Erase Install (IPSW)"
#define RESTORE_VARIANT_UPGRADE_INSTALL "Upgrade Install (IPSW)"
@@ -83,9 +84,6 @@ void idevicerestore_set_flags(struct idevicerestore_client_t* client, int flags)
void idevicerestore_set_ipsw(struct idevicerestore_client_t* client, const char* path);
void idevicerestore_set_cache_path(struct idevicerestore_client_t* client, const char* path);
void idevicerestore_set_progress_callback(struct idevicerestore_client_t* client, idevicerestore_progress_cb_t cbfunc, void* userdata);
void idevicerestore_set_info_stream(FILE* strm);
void idevicerestore_set_error_stream(FILE* strm);
void idevicerestore_set_debug_stream(FILE* strm);
int idevicerestore_start(struct idevicerestore_client_t* client);
const char* idevicerestore_get_error(void);
+39 -39
View File
@@ -38,13 +38,13 @@ static img3_file* img3_parse_file(const unsigned char* data, unsigned int size)
img3_element* element;
img3_header* header = (img3_header*) data;
if (header->signature != kImg3Container) {
error("ERROR: Invalid IMG3 file\n");
logger(LL_ERROR, "Invalid IMG3 file\n");
return NULL;
}
img3_file* image = (img3_file*) malloc(sizeof(img3_file));
if (image == NULL) {
error("ERROR: Unable to allocate memory for IMG3 file\n");
logger(LL_ERROR, "Unable to allocate memory for IMG3 file\n");
return NULL;
}
memset(image, '\0', sizeof(img3_file));
@@ -54,7 +54,7 @@ static img3_file* img3_parse_file(const unsigned char* data, unsigned int size)
image->header = (img3_header*) malloc(sizeof(img3_header));
if (image->header == NULL) {
error("ERROR: Unable to allocate memory for IMG3 header\n");
logger(LL_ERROR, "Unable to allocate memory for IMG3 header\n");
img3_free(image);
return NULL;
}
@@ -68,129 +68,129 @@ static img3_file* img3_parse_file(const unsigned char* data, unsigned int size)
case kTypeElement:
element = img3_parse_element(&data[data_offset]);
if (element == NULL) {
error("ERROR: Unable to parse TYPE element\n");
logger(LL_ERROR, "Unable to parse TYPE element\n");
img3_free(image);
return NULL;
}
image->elements[image->num_elements++] = element;
debug("Parsed TYPE element\n");
logger(LL_DEBUG, "Parsed TYPE element\n");
break;
case kDataElement:
element = img3_parse_element(&data[data_offset]);
if (element == NULL) {
error("ERROR: Unable to parse DATA element\n");
logger(LL_ERROR, "Unable to parse DATA element\n");
img3_free(image);
return NULL;
}
image->elements[image->num_elements++] = element;
debug("Parsed DATA element\n");
logger(LL_DEBUG, "Parsed DATA element\n");
break;
case kVersElement:
element = img3_parse_element(&data[data_offset]);
if (element == NULL) {
error("ERROR: Unable to parse VERS element\n");
logger(LL_ERROR, "Unable to parse VERS element\n");
img3_free(image);
return NULL;
}
image->elements[image->num_elements++] = element;
debug("Parsed VERS element\n");
logger(LL_DEBUG, "Parsed VERS element\n");
break;
case kSepoElement:
element = img3_parse_element(&data[data_offset]);
if (element == NULL) {
error("ERROR: Unable to parse SEPO element\n");
logger(LL_ERROR, "Unable to parse SEPO element\n");
img3_free(image);
return NULL;
}
image->elements[image->num_elements++] = element;
debug("Parsed SEPO element\n");
logger(LL_DEBUG, "Parsed SEPO element\n");
break;
case kBordElement:
element = img3_parse_element(&data[data_offset]);
if (element == NULL) {
error("ERROR: Unable to parse BORD element\n");
logger(LL_ERROR, "Unable to parse BORD element\n");
img3_free(image);
return NULL;
}
image->elements[image->num_elements++] = element;
debug("Parsed BORD element\n");
logger(LL_DEBUG, "Parsed BORD element\n");
break;
case kChipElement:
element = img3_parse_element(&data[data_offset]);
if (element == NULL) {
error("ERROR: Unable to parse CHIP element\n");
logger(LL_ERROR, "Unable to parse CHIP element\n");
img3_free(image);
return NULL;
}
image->elements[image->num_elements++] = element;
debug("Parsed CHIP element\n");
logger(LL_DEBUG, "Parsed CHIP element\n");
break;
case kKbagElement:
element = img3_parse_element(&data[data_offset]);
if (element == NULL) {
error("ERROR: Unable to parse first KBAG element\n");
logger(LL_ERROR, "Unable to parse first KBAG element\n");
img3_free(image);
return NULL;
}
image->elements[image->num_elements++] = element;
debug("Parsed KBAG element\n");
logger(LL_DEBUG, "Parsed KBAG element\n");
break;
case kEcidElement:
element = img3_parse_element(&data[data_offset]);
if (element == NULL) {
error("ERROR: Unable to parse ECID element\n");
logger(LL_ERROR, "Unable to parse ECID element\n");
img3_free(image);
return NULL;
}
image->idx_ecid_element = image->num_elements;
image->elements[image->num_elements++] = element;
debug("Parsed ECID element\n");
logger(LL_DEBUG, "Parsed ECID element\n");
break;
case kShshElement:
element = img3_parse_element(&data[data_offset]);
if (element == NULL) {
error("ERROR: Unable to parse SHSH element\n");
logger(LL_ERROR, "Unable to parse SHSH element\n");
img3_free(image);
return NULL;
}
image->idx_shsh_element = image->num_elements;
image->elements[image->num_elements++] = element;
debug("Parsed SHSH element\n");
logger(LL_DEBUG, "Parsed SHSH element\n");
break;
case kCertElement:
element = img3_parse_element(&data[data_offset]);
if (element == NULL) {
error("ERROR: Unable to parse CERT element\n");
logger(LL_ERROR, "Unable to parse CERT element\n");
img3_free(image);
return NULL;
}
image->idx_cert_element = image->num_elements;
image->elements[image->num_elements++] = element;
debug("Parsed CERT element\n");
logger(LL_DEBUG, "Parsed CERT element\n");
break;
case kUnknElement:
element = img3_parse_element(&data[data_offset]);
if (element == NULL) {
error("ERROR: Unable to parse UNKN element\n");
logger(LL_ERROR, "Unable to parse UNKN element\n");
img3_free(image);
return NULL;
}
image->elements[image->num_elements++] = element;
debug("Parsed UNKN element\n");
logger(LL_DEBUG, "Parsed UNKN element\n");
break;
default:
error("ERROR: Unknown IMG3 element type %08x\n", current->signature);
logger(LL_ERROR, "Unknown IMG3 element type %08x\n", current->signature);
img3_free(image);
return NULL;
}
@@ -204,14 +204,14 @@ static img3_element* img3_parse_element(const unsigned char* data) {
img3_element_header* element_header = (img3_element_header*) data;
img3_element* element = (img3_element*) malloc(sizeof(img3_element));
if (element == NULL) {
error("ERROR: Unable to allocate memory for IMG3 element\n");
logger(LL_ERROR, "Unable to allocate memory for IMG3 element\n");
return NULL;
}
memset(element, '\0', sizeof(img3_element));
element->data = (unsigned char*) malloc(element_header->full_size);
if (element->data == NULL) {
error("ERROR: Unable to allocate memory for IMG3 element data\n");
logger(LL_ERROR, "Unable to allocate memory for IMG3 element data\n");
free(element);
return NULL;
}
@@ -254,21 +254,21 @@ static int img3_replace_signature(img3_file* image, const unsigned char* signatu
int offset = 0;
img3_element* ecid = img3_parse_element(&signature[offset]);
if (ecid == NULL || ecid->type != kEcidElement) {
error("ERROR: Unable to find ECID element in signature\n");
logger(LL_ERROR, "Unable to find ECID element in signature\n");
return -1;
}
offset += ecid->header->full_size;
img3_element* shsh = img3_parse_element(&signature[offset]);
if (shsh == NULL || shsh->type != kShshElement) {
error("ERROR: Unable to find SHSH element in signature\n");
logger(LL_ERROR, "Unable to find SHSH element in signature\n");
return -1;
}
offset += shsh->header->full_size;
img3_element* cert = img3_parse_element(&signature[offset]);
if (cert == NULL || cert->type != kCertElement) {
error("ERROR: Unable to find CERT element in signature\n");
logger(LL_ERROR, "Unable to find CERT element in signature\n");
return -1;
}
offset += cert->header->full_size;
@@ -364,11 +364,11 @@ static int img3_get_data(img3_file* image, unsigned char** pdata, unsigned int*
size += image->elements[i]->header->full_size;
}
info("reconstructed size: %d\n", size);
logger(LL_INFO, "reconstructed size: %d\n", size);
unsigned char* data = (unsigned char*) malloc(size);
if (data == NULL) {
error("ERROR: Unable to allocate memory for IMG3 data\n");
logger(LL_ERROR, "Unable to allocate memory for IMG3 data\n");
return -1;
}
@@ -390,7 +390,7 @@ static int img3_get_data(img3_file* image, unsigned char** pdata, unsigned int*
}
if (offset != size) {
error("ERROR: Incorrectly sized image data\n");
logger(LL_ERROR, "Incorrectly sized image data\n");
free(data);
*pdata = 0;
*psize = 0;
@@ -412,31 +412,31 @@ int img3_stitch_component(const char* component_name, const unsigned char* compo
return -1;
}
info("Personalizing IMG3 component %s...\n", component_name);
logger(LL_INFO, "Personalizing IMG3 component %s...\n", component_name);
/* parse current component as img3 */
img3 = img3_parse_file(component_data, component_size);
if (img3 == NULL) {
error("ERROR: Unable to parse %s IMG3 file\n", component_name);
logger(LL_ERROR, "Unable to parse %s IMG3 file\n", component_name);
return -1;
}
if (((img3_element_header*)blob)->full_size != blob_size) {
error("ERROR: Invalid blob passed for %s IMG3: The size %d embedded in the blob does not match the passed size of %d\n", component_name, ((img3_element_header*)blob)->full_size, blob_size);
logger(LL_ERROR, "Invalid blob passed for %s IMG3: The size %d embedded in the blob does not match the passed size of %d\n", component_name, ((img3_element_header*)blob)->full_size, blob_size);
img3_free(img3);
return -1;
}
/* personalize the component using the blob */
if (img3_replace_signature(img3, blob) < 0) {
error("ERROR: Unable to replace %s IMG3 signature\n", component_name);
logger(LL_ERROR, "Unable to replace %s IMG3 signature\n", component_name);
img3_free(img3);
return -1;
}
/* get the img3 file as data */
if (img3_get_data(img3, &outbuf, &outsize) < 0) {
error("ERROR: Unable to reconstruct %s IMG3\n", component_name);
logger(LL_ERROR, "Unable to reconstruct %s IMG3\n", component_name);
img3_free(img3);
return -1;
}
+12 -12
View File
@@ -204,7 +204,7 @@ static void asn1_write_element(unsigned char **p, unsigned int *length, unsigned
}
} break;
default:
fprintf(stderr, "ERROR: %s: type %02x is not implemented\n", __func__, type);
logger(LL_ERROR, "%s: type %02x is not implemented\n", __func__, type);
return;
}
}
@@ -415,15 +415,15 @@ int img4_stitch_component(const char* component_name, const unsigned char* compo
}
if (tss_response_get_ap_img4_ticket(tss_response, &blob, &blob_size) != 0) {
error("ERROR: %s: Failed to get ApImg4Ticket from TSS response\n", __func__);
logger(LL_ERROR, "%s: Failed to get ApImg4Ticket from TSS response\n", __func__);
return -1;
}
info("Personalizing IMG4 component %s...\n", component_name);
logger(LL_INFO, "Personalizing IMG4 component %s...\n", component_name);
/* first we need check if we have to change the tag for the given component */
const void *tag = asn1_find_element(1, ASN1_IA5_STRING, component_data);
if (tag) {
debug("Tag found\n");
logger(LL_DEBUG, "Tag found\n");
if (strcmp(component_name, "RestoreKernelCache") == 0) {
memcpy((void*)tag, "rkrn", 4);
} else if (strcmp(component_name, "RestoreDeviceTree") == 0) {
@@ -467,22 +467,22 @@ int img4_stitch_component(const char* component_name, const unsigned char* compo
if (tbm_dict) {
plist_t dt = plist_dict_get_item(tbm_dict, "ucon");
if (!dt) {
error("ERROR: %s: Missing ucon node in %s-TBM dictionary\n", __func__, component_name);
logger(LL_ERROR, "%s: Missing ucon node in %s-TBM dictionary\n", __func__, component_name);
return -1;
}
ucon_data = plist_get_data_ptr(dt, &ucon_size);
if (!ucon_data) {
error("ERROR: %s: Missing ucon data in %s-TBM dictionary\n", __func__, component_name);
logger(LL_ERROR, "%s: Missing ucon data in %s-TBM dictionary\n", __func__, component_name);
return -1;
}
dt = plist_dict_get_item(tbm_dict, "ucer");
if (!dt) {
error("ERROR: %s: Missing ucer data node in %s-TBM dictionary\n", __func__, component_name);
logger(LL_ERROR, "%s: Missing ucer data node in %s-TBM dictionary\n", __func__, component_name);
return -1;
}
ucer_data = plist_get_data_ptr(dt, &ucer_size);
if (!ucer_data) {
error("ERROR: %s: Missing ucer data in %s-TBM dictionary\n", __func__, component_name);
logger(LL_ERROR, "%s: Missing ucer data in %s-TBM dictionary\n", __func__, component_name);
return -1;
}
}
@@ -683,7 +683,7 @@ int img4_stitch_component(const char* component_name, const unsigned char* compo
free(img4header);
}
free(additional_data);
error("ERROR: out of memory when personalizing IMG4 component %s\n", component_name);
logger(LL_ERROR, "out of memory when personalizing IMG4 component %s\n", component_name);
return -1;
}
p = outbuf;
@@ -825,7 +825,7 @@ static void _manifest_write_component(unsigned char **p, unsigned int *length, c
tbmtag = "tbmr";
}
if (!tbmtag) {
error("ERROR: Unexpected TMBDigests for comp '%s'\n", tag);
logger(LL_ERROR, "Unexpected TMBDigests for comp '%s'\n", tag);
} else {
_manifest_write_key_value(&tmp, &tmp_len, tbmtag, ASN1_OCTET_STRING, (void*)data, datalen);
}
@@ -918,10 +918,10 @@ int img4_create_local_manifest(plist_t request, plist_t build_identity, plist_t*
comp = _img4_get_component_tag(key);
}
if (!comp) {
debug("DEBUG: %s: Unhandled component '%s'\n", __func__, key);
logger(LL_DEBUG, "%s: Unhandled component '%s'\n", __func__, key);
_manifest_write_component(&p, &length, key, val);
} else {
debug("DEBUG: found component %s (%s)\n", comp, key);
logger(LL_DEBUG, "found component %s (%s)\n", comp, key);
_manifest_write_component(&p, &length, comp, val);
}
}
+135 -107
View File
@@ -69,7 +69,7 @@ int ipsw_print_info(const char* path)
struct stat fst;
if (stat(path, &fst) != 0) {
error("ERROR: '%s': %s\n", path, strerror(errno));
logger(LL_ERROR, "'%s': %s\n", path, strerror(errno));
return -1;
}
@@ -78,7 +78,7 @@ int ipsw_print_info(const char* path)
if (S_ISDIR(fst.st_mode)) {
snprintf(thepath, sizeof(thepath), "%s/BuildManifest.plist", path);
if (stat(thepath, &fst) != 0) {
error("ERROR: '%s': %s\n", thepath, strerror(errno));
logger(LL_ERROR, "'%s': %s\n", thepath, strerror(errno));
return -1;
}
} else {
@@ -87,13 +87,13 @@ int ipsw_print_info(const char* path)
FILE* f = fopen(thepath, "r");
if (!f) {
error("ERROR: Can't open '%s': %s\n", thepath, strerror(errno));
logger(LL_ERROR, "Can't open '%s': %s\n", thepath, strerror(errno));
return -1;
}
uint32_t magic;
if (fread(&magic, 1, 4, f) != 4) {
fclose(f);
fprintf(stderr, "Failed to read from '%s'\n", path);
logger(LL_ERROR, "Failed to read from '%s'\n", path);
return -1;
}
fclose(f);
@@ -106,7 +106,7 @@ int ipsw_print_info(const char* path)
unsigned int rlen = 0;
if (ipsw_extract_to_memory(ipsw, "BuildManifest.plist", (unsigned char**)&plist_buf, &rlen) < 0) {
ipsw_close(ipsw);
error("ERROR: Failed to extract BuildManifest.plist from IPSW!\n");
logger(LL_ERROR, "Failed to extract BuildManifest.plist from IPSW!\n");
return -1;
}
ipsw_close(ipsw);
@@ -114,7 +114,7 @@ int ipsw_print_info(const char* path)
} else {
size_t rlen = 0;
if (read_file(thepath, (void**)&plist_buf, &rlen) < 0) {
error("ERROR: Failed to read BuildManifest.plist!\n");
logger(LL_ERROR, "Failed to read BuildManifest.plist!\n");
return -1;
}
plist_len = (uint32_t)rlen;
@@ -302,13 +302,13 @@ ipsw_archive_t ipsw_open(const char* ipsw)
int err = 0;
ipsw_archive_t archive = (ipsw_archive_t)calloc(1, sizeof(struct ipsw_archive));
if (archive == NULL) {
error("ERROR: Out of memory\n");
logger(LL_ERROR, "Out of memory\n");
return NULL;
}
struct stat fst;
if (stat(ipsw, &fst) != 0) {
error("ERROR: ipsw_open %s: %s\n", ipsw, strerror(errno));
logger(LL_ERROR, "ipsw_open %s: %s\n", ipsw, strerror(errno));
return NULL;
}
if (S_ISDIR(fst.st_mode)) {
@@ -316,7 +316,7 @@ ipsw_archive_t ipsw_open(const char* ipsw)
} else {
struct zip *zip = zip_open(ipsw, 0, &err);
if (zip == NULL) {
error("ERROR: zip_open: %s: %d\n", ipsw, err);
logger(LL_ERROR, "zip_open: %s: %d\n", ipsw, err);
free(archive);
return NULL;
}
@@ -347,7 +347,7 @@ int ipsw_is_directory(const char* ipsw)
int ipsw_get_file_size(ipsw_archive_t ipsw, const char* infile, uint64_t* size)
{
if (ipsw == NULL) {
error("ERROR: Invalid archive\n");
logger(LL_ERROR, "Invalid archive\n");
return -1;
}
@@ -355,12 +355,12 @@ int ipsw_get_file_size(ipsw_archive_t ipsw, const char* infile, uint64_t* size)
int err = 0;
struct zip *zip = zip_open(ipsw->path, 0, &err);
if (zip == NULL) {
error("ERROR: zip_open: %s: %d\n", ipsw->path, err);
logger(LL_ERROR, "zip_open: %s: %d\n", ipsw->path, err);
return -1;
}
int zindex = zip_name_locate(zip, infile, 0);
if (zindex < 0) {
error("ERROR: zip_name_locate: %s\n", infile);
logger(LL_ERROR, "zip_name_locate: %s\n", infile);
zip_unchange_all(zip);
zip_close(zip);
return -1;
@@ -369,7 +369,7 @@ int ipsw_get_file_size(ipsw_archive_t ipsw, const char* infile, uint64_t* size)
struct zip_stat zstat;
zip_stat_init(&zstat);
if (zip_stat_index(zip, zindex, 0, &zstat) != 0) {
error("ERROR: zip_stat_index: %s\n", infile);
logger(LL_ERROR, "zip_stat_index: %s\n", infile);
zip_unchange_all(zip);
zip_close(zip);
return -1;
@@ -398,7 +398,7 @@ int ipsw_extract_to_file_with_progress(ipsw_archive_t ipsw, const char* infile,
int ret = 0;
if (!ipsw || !infile || !outfile) {
error("ERROR: Invalid argument\n");
logger(LL_ERROR, "Invalid argument\n");
return -1;
}
@@ -408,7 +408,7 @@ int ipsw_extract_to_file_with_progress(ipsw_archive_t ipsw, const char* infile,
int err = 0;
struct zip *zip = zip_open(ipsw->path, 0, &err);
if (zip == NULL) {
error("ERROR: zip_open: %s: %d\n", ipsw->path, err);
logger(LL_ERROR, "zip_open: %s: %d\n", ipsw->path, err);
return -1;
}
@@ -416,7 +416,7 @@ int ipsw_extract_to_file_with_progress(ipsw_archive_t ipsw, const char* infile,
if (zindex < 0) {
zip_unchange_all(zip);
zip_close(zip);
error("ERROR: zip_name_locate: %s\n", infile);
logger(LL_ERROR, "zip_name_locate: %s\n", infile);
return -1;
}
@@ -425,7 +425,7 @@ int ipsw_extract_to_file_with_progress(ipsw_archive_t ipsw, const char* infile,
if (zip_stat_index(zip, zindex, 0, &zstat) != 0) {
zip_unchange_all(zip);
zip_close(zip);
error("ERROR: zip_stat_index: %s\n", infile);
logger(LL_ERROR, "zip_stat_index: %s\n", infile);
return -1;
}
@@ -433,7 +433,7 @@ int ipsw_extract_to_file_with_progress(ipsw_archive_t ipsw, const char* infile,
if (buffer == NULL) {
zip_unchange_all(zip);
zip_close(zip);
error("ERROR: Unable to allocate memory\n");
logger(LL_ERROR, "Unable to allocate memory\n");
return -1;
}
@@ -441,7 +441,7 @@ int ipsw_extract_to_file_with_progress(ipsw_archive_t ipsw, const char* infile,
if (zfile == NULL) {
zip_unchange_all(zip);
zip_close(zip);
error("ERROR: zip_fopen_index: %s\n", infile);
logger(LL_ERROR, "zip_fopen_index: %s\n", infile);
return -1;
}
@@ -450,13 +450,15 @@ int ipsw_extract_to_file_with_progress(ipsw_archive_t ipsw, const char* infile,
zip_fclose(zfile);
zip_unchange_all(zip);
zip_close(zip);
error("ERROR: Unable to open output file: %s\n", outfile);
logger(LL_ERROR, "Unable to open output file: %s\n", outfile);
return -1;
}
if (print_progress) {
register_progress('IPSW', "Extracting");
}
uint64_t i, bytes = 0;
int count, size = BUFSIZE;
double progress;
for(i = zstat.size; i > 0; i -= count) {
if (cancel_flag) {
break;
@@ -468,23 +470,26 @@ int ipsw_extract_to_file_with_progress(ipsw_archive_t ipsw, const char* infile,
int zep = 0;
int sep = 0;
zip_file_error_get(zfile, &zep, &sep);
error("ERROR: zip_fread: %s %d %d\n", infile, zep, sep);
logger(LL_ERROR, "zip_fread: %s %d %d\n", infile, zep, sep);
ret = -1;
break;
}
if (fwrite(buffer, 1, count, fd) != count) {
error("ERROR: Writing to '%s' failed: %s\n", outfile, strerror(errno));
logger(LL_ERROR, "Writing to '%s' failed: %s\n", outfile, strerror(errno));
ret = -1;
break;
}
bytes += size;
if (print_progress) {
progress = ((double)bytes / (double)zstat.size) * 100.0;
print_progress_bar(progress);
double progress = ((double)bytes / (double)zstat.size);
set_progress('IPSW', progress);
}
}
free(buffer);
if (print_progress) {
finalize_progress('IPSW');
}
fclose(fd);
zip_fclose(zfile);
zip_unchange_all(zip);
@@ -498,7 +503,7 @@ int ipsw_extract_to_file_with_progress(ipsw_archive_t ipsw, const char* infile,
goto leave;
}
if (!realpath(filepath, actual_filepath)) {
error("ERROR: realpath failed on %s: %s\n", filepath, strerror(errno));
logger(LL_ERROR, "realpath failed on %s: %s\n", filepath, strerror(errno));
ret = -1;
goto leave;
} else {
@@ -512,21 +517,21 @@ int ipsw_extract_to_file_with_progress(ipsw_archive_t ipsw, const char* infile,
}
FILE *fi = fopen(actual_filepath, "rb");
if (!fi) {
error("ERROR: fopen: %s: %s\n", actual_filepath, strerror(errno));
logger(LL_ERROR, "fopen: %s: %s\n", actual_filepath, strerror(errno));
ret = -1;
goto leave;
}
struct stat fst;
if (fstat(fileno(fi), &fst) != 0) {
fclose(fi);
error("ERROR: fstat: %s: %s\n", actual_filepath, strerror(errno));
logger(LL_ERROR, "fstat: %s: %s\n", actual_filepath, strerror(errno));
ret = -1;
goto leave;
}
FILE *fo = fopen(actual_outfile, "wb");
if (!fo) {
fclose(fi);
error("ERROR: fopen: %s: %s\n", actual_outfile, strerror(errno));
logger(LL_ERROR, "fopen: %s: %s\n", actual_outfile, strerror(errno));
ret = -1;
goto leave;
}
@@ -534,34 +539,39 @@ int ipsw_extract_to_file_with_progress(ipsw_archive_t ipsw, const char* infile,
if (buffer == NULL) {
fclose(fi);
fclose(fo);
error("ERROR: Unable to allocate memory\n");
logger(LL_ERROR, "Unable to allocate memory\n");
ret = -1;
goto leave;;
}
if (print_progress) {
register_progress('IPSW', "Extracting");
}
uint64_t bytes = 0;
double progress;
while (!feof(fi)) {
if (cancel_flag) {
break;
}
ssize_t r = fread(buffer, 1, BUFSIZE, fi);
if (r < 0) {
error("ERROR: fread failed: %s\n", strerror(errno));
logger(LL_ERROR, "fread failed: %s\n", strerror(errno));
ret = -1;
break;
}
if (fwrite(buffer, 1, r, fo) != r) {
error("ERROR: Writing to '%s' failed: %s\n", actual_outfile, strerror(errno));
logger(LL_ERROR, "Writing to '%s' failed: %s\n", actual_outfile, strerror(errno));
ret = -1;
break;
}
bytes += r;
if (print_progress) {
progress = ((double)bytes / (double)fst.st_size) * 100.0;
print_progress_bar(progress);
double progress = ((double)bytes / (double)fst.st_size);
set_progress('IPSW', progress);
}
}
if (print_progress) {
finalize_progress('IPSW');
}
free(buffer);
fclose(fi);
@@ -592,7 +602,7 @@ int ipsw_file_exists(ipsw_archive_t ipsw, const char* infile)
int err = 0;
struct zip *zip = zip_open(ipsw->path, 0, &err);
if (zip == NULL) {
error("ERROR: zip_open: %s: %d\n", ipsw->path, err);
logger(LL_ERROR, "zip_open: %s: %d\n", ipsw->path, err);
return 0;
}
int zindex = zip_name_locate(zip, infile, 0);
@@ -618,7 +628,7 @@ int ipsw_extract_to_memory(ipsw_archive_t ipsw, const char* infile, unsigned cha
size_t size = 0;
unsigned char* buffer = NULL;
if (ipsw == NULL) {
error("ERROR: Invalid archive\n");
logger(LL_ERROR, "Invalid archive\n");
return -1;
}
@@ -626,7 +636,7 @@ int ipsw_extract_to_memory(ipsw_archive_t ipsw, const char* infile, unsigned cha
int err = 0;
struct zip *zip = zip_open(ipsw->path, 0, &err);
if (zip == NULL) {
error("ERROR: zip_open: %s: %d\n", ipsw->path, err);
logger(LL_ERROR, "zip_open: %s: %d\n", ipsw->path, err);
return -1;
}
@@ -634,7 +644,7 @@ int ipsw_extract_to_memory(ipsw_archive_t ipsw, const char* infile, unsigned cha
if (zindex < 0) {
zip_unchange_all(zip);
zip_close(zip);
debug("NOTE: zip_name_locate: '%s' not found in archive.\n", infile);
logger(LL_DEBUG, "zip_name_locate: '%s' not found in archive.\n", infile);
return -1;
}
@@ -643,7 +653,7 @@ int ipsw_extract_to_memory(ipsw_archive_t ipsw, const char* infile, unsigned cha
if (zip_stat_index(zip, zindex, 0, &zstat) != 0) {
zip_unchange_all(zip);
zip_close(zip);
error("ERROR: zip_stat_index: %s\n", infile);
logger(LL_ERROR, "zip_stat_index: %s\n", infile);
return -1;
}
@@ -651,14 +661,14 @@ int ipsw_extract_to_memory(ipsw_archive_t ipsw, const char* infile, unsigned cha
if (zfile == NULL) {
zip_unchange_all(zip);
zip_close(zip);
error("ERROR: zip_fopen_index: %s\n", infile);
logger(LL_ERROR, "zip_fopen_index: %s\n", infile);
return -1;
}
size = zstat.size;
buffer = (unsigned char*) malloc(size+1);
if (buffer == NULL) {
error("ERROR: Out of memory\n");
logger(LL_ERROR, "Out of memory\n");
zip_fclose(zfile);
zip_unchange_all(zip);
zip_close(zip);
@@ -673,11 +683,11 @@ int ipsw_extract_to_memory(ipsw_archive_t ipsw, const char* infile, unsigned cha
int zep = 0;
int sep = 0;
zip_file_error_get(zfile, &zep, &sep);
error("ERROR: zip_fread: %s %d %d\n", infile, zep, sep);
logger(LL_ERROR, "zip_fread: %s %d %d\n", infile, zep, sep);
free(buffer);
return -1;
} else if (zr != size) {
error("ERROR: zip_fread: %s got only %lld of %zu\n", infile, zr, size);
logger(LL_ERROR, "zip_fread: %s got only %lld of %zu\n", infile, zr, size);
free(buffer);
return -1;
}
@@ -691,14 +701,14 @@ int ipsw_extract_to_memory(ipsw_archive_t ipsw, const char* infile, unsigned cha
#else
if (lstat(filepath, &fst) != 0) {
#endif
error("ERROR: %s: stat failed for %s: %s\n", __func__, filepath, strerror(errno));
logger(LL_ERROR, "%s: stat failed for %s: %s\n", __func__, filepath, strerror(errno));
free(filepath);
return -1;
}
size = fst.st_size;
buffer = (unsigned char*)malloc(size+1);
if (buffer == NULL) {
error("ERROR: Out of memory\n");
logger(LL_ERROR, "Out of memory\n");
free(filepath);
return -1;
}
@@ -706,7 +716,7 @@ int ipsw_extract_to_memory(ipsw_archive_t ipsw, const char* infile, unsigned cha
#ifndef WIN32
if (S_ISLNK(fst.st_mode)) {
if (readlink(filepath, (char*)buffer, size) < 0) {
error("ERROR: %s: readlink failed for %s: %s\n", __func__, filepath, strerror(errno));
logger(LL_ERROR, "%s: readlink failed for %s: %s\n", __func__, filepath, strerror(errno));
free(filepath);
free(buffer);
return -1;
@@ -715,14 +725,14 @@ int ipsw_extract_to_memory(ipsw_archive_t ipsw, const char* infile, unsigned cha
#endif
FILE *f = fopen(filepath, "rb");
if (!f) {
error("ERROR: %s: fopen failed for %s: %s\n", __func__, filepath, strerror(errno));
logger(LL_ERROR, "%s: fopen failed for %s: %s\n", __func__, filepath, strerror(errno));
free(filepath);
free(buffer);
return -2;
}
if (fread(buffer, 1, size, f) != size) {
fclose(f);
error("ERROR: %s: fread failed for %s: %s\n", __func__, filepath, strerror(errno));
logger(LL_ERROR, "%s: fread failed for %s: %s\n", __func__, filepath, strerror(errno));
free(filepath);
free(buffer);
return -1;
@@ -748,7 +758,7 @@ int ipsw_extract_send(ipsw_archive_t ipsw, const char* infile, int blocksize, ip
size_t total_size = 0;
if (ipsw == NULL) {
error("ERROR: Invalid archive\n");
logger(LL_ERROR, "Invalid archive\n");
return -1;
}
@@ -756,7 +766,7 @@ int ipsw_extract_send(ipsw_archive_t ipsw, const char* infile, int blocksize, ip
int err = 0;
struct zip *zip = zip_open(ipsw->path, 0, &err);
if (zip == NULL) {
error("ERROR: zip_open: %s: %d\n", ipsw->path, err);
logger(LL_ERROR, "zip_open: %s: %d\n", ipsw->path, err);
return -1;
}
@@ -764,7 +774,7 @@ int ipsw_extract_send(ipsw_archive_t ipsw, const char* infile, int blocksize, ip
if (zindex < 0) {
zip_unchange_all(zip);
zip_close(zip);
debug("NOTE: zip_name_locate: '%s' not found in archive.\n", infile);
logger(LL_DEBUG, "zip_name_locate: '%s' not found in archive.\n", infile);
return -1;
}
@@ -773,7 +783,7 @@ int ipsw_extract_send(ipsw_archive_t ipsw, const char* infile, int blocksize, ip
if (zip_stat_index(zip, zindex, 0, &zstat) != 0) {
zip_unchange_all(zip);
zip_close(zip);
error("ERROR: zip_stat_index: %s\n", infile);
logger(LL_ERROR, "zip_stat_index: %s\n", infile);
return -1;
}
@@ -781,7 +791,7 @@ int ipsw_extract_send(ipsw_archive_t ipsw, const char* infile, int blocksize, ip
if (zfile == NULL) {
zip_unchange_all(zip);
zip_close(zip);
error("ERROR: zip_fopen_index: %s\n", infile);
logger(LL_ERROR, "zip_fopen_index: %s\n", infile);
return -1;
}
@@ -791,7 +801,7 @@ int ipsw_extract_send(ipsw_archive_t ipsw, const char* infile, int blocksize, ip
zip_fclose(zfile);
zip_unchange_all(zip);
zip_close(zip);
error("ERROR: Out of memory\n");
logger(LL_ERROR, "Out of memory\n");
return -1;
}
@@ -800,14 +810,14 @@ int ipsw_extract_send(ipsw_archive_t ipsw, const char* infile, int blocksize, ip
if (size > blocksize) size = blocksize;
zip_int64_t zr = zip_fread(zfile, buffer, size);
if (zr < 0) {
error("ERROR: %s: zip_fread: %s\n", __func__, infile);
logger(LL_ERROR, "%s: zip_fread: %s\n", __func__, infile);
break;
} else if (zr == 0) {
// EOF
break;
}
if (send_callback(ctx, buffer, zr, done, total_size) < 0) {
error("ERROR: %s: send failed\n", __func__);
logger(LL_ERROR, "%s: send failed\n", __func__);
break;
}
done += zr;
@@ -824,14 +834,14 @@ int ipsw_extract_send(ipsw_archive_t ipsw, const char* infile, int blocksize, ip
#else
if (lstat(filepath, &fst) != 0) {
#endif
error("ERROR: %s: stat failed for %s: %s\n", __func__, filepath, strerror(errno));
logger(LL_ERROR, "%s: stat failed for %s: %s\n", __func__, filepath, strerror(errno));
free(filepath);
return -1;
}
total_size = fst.st_size;
buffer = (unsigned char*)malloc(blocksize);
if (buffer == NULL) {
error("ERROR: Out of memory\n");
logger(LL_ERROR, "Out of memory\n");
free(filepath);
return -1;
}
@@ -840,7 +850,7 @@ int ipsw_extract_send(ipsw_archive_t ipsw, const char* infile, int blocksize, ip
if (S_ISLNK(fst.st_mode)) {
ssize_t rl = readlink(filepath, (char*)buffer, (total_size > blocksize) ? blocksize : total_size);
if (rl < 0) {
error("ERROR: %s: readlink failed for %s: %s\n", __func__, filepath, strerror(errno));
logger(LL_ERROR, "%s: readlink failed for %s: %s\n", __func__, filepath, strerror(errno));
free(filepath);
free(buffer);
return -1;
@@ -850,7 +860,7 @@ int ipsw_extract_send(ipsw_archive_t ipsw, const char* infile, int blocksize, ip
#endif
FILE *f = fopen(filepath, "rb");
if (!f) {
error("ERROR: %s: fopen failed for %s: %s\n", __func__, filepath, strerror(errno));
logger(LL_ERROR, "%s: fopen failed for %s: %s\n", __func__, filepath, strerror(errno));
free(filepath);
free(buffer);
return -2;
@@ -861,11 +871,11 @@ int ipsw_extract_send(ipsw_archive_t ipsw, const char* infile, int blocksize, ip
if (size > blocksize) size = blocksize;
size_t fr = fread(buffer, 1, size, f);
if (fr != size) {
error("ERROR: %s: fread failed for %s: %s\n", __func__, filepath, strerror(errno));
logger(LL_ERROR, "%s: fread failed for %s: %s\n", __func__, filepath, strerror(errno));
break;
}
if (send_callback(ctx, buffer, fr, done, total_size) < 0) {
error("ERROR: %s: send failed\n", __func__);
logger(LL_ERROR, "%s: send failed\n", __func__);
break;
}
done += fr;
@@ -879,7 +889,7 @@ int ipsw_extract_send(ipsw_archive_t ipsw, const char* infile, int blocksize, ip
}
if (done < total_size) {
error("ERROR: %s: Sending file data for %s failed (sent %" PRIu64 "/%" PRIu64 ")\n", __func__, infile, (uint64_t)done, (uint64_t)total_size);
logger(LL_ERROR, "%s: Sending file data for %s failed (sent %" PRIu64 "/%" PRIu64 ")\n", __func__, infile, (uint64_t)done, (uint64_t)total_size);
return -1;
}
@@ -941,7 +951,7 @@ static int ipsw_list_contents_recurse(ipsw_archive_t ipsw, const char *path, ips
DIR *dirp = opendir(base);
if (!dirp) {
error("ERROR: failed to open directory %s\n", base);
logger(LL_ERROR, "failed to open directory %s\n", base);
free(base);
return -1;
}
@@ -968,7 +978,7 @@ static int ipsw_list_contents_recurse(ipsw_archive_t ipsw, const char *path, ips
ret = lstat(fpath, &st);
#endif
if (ret != 0) {
error("ERROR: %s: stat failed for %s: %s\n", __func__, fpath, strerror(errno));
logger(LL_ERROR, "%s: stat failed for %s: %s\n", __func__, fpath, strerror(errno));
free(fpath);
free(subpath);
break;
@@ -993,7 +1003,7 @@ int ipsw_list_contents(ipsw_archive_t ipsw, ipsw_list_cb cb, void *ctx)
int ret = 0;
if (ipsw == NULL) {
error("ERROR: Invalid IPSW archive\n");
logger(LL_ERROR, "Invalid IPSW archive\n");
return -1;
}
@@ -1001,13 +1011,13 @@ int ipsw_list_contents(ipsw_archive_t ipsw, ipsw_list_cb cb, void *ctx)
int err = 0;
struct zip *zip = zip_open(ipsw->path, 0, &err);
if (zip == NULL) {
error("ERROR: zip_open: %s: %d\n", ipsw->path, err);
logger(LL_ERROR, "zip_open: %s: %d\n", ipsw->path, err);
return -1;
}
int64_t entries = zip_get_num_entries(zip, 0);
if (entries < 0) {
error("ERROR: zip_get_num_entries failed\n");
logger(LL_ERROR, "zip_get_num_entries failed\n");
return -1;
}
@@ -1016,7 +1026,7 @@ int ipsw_list_contents(ipsw_archive_t ipsw, ipsw_list_cb cb, void *ctx)
zip_stat_init(&stat);
if (zip_stat_index(zip, index, 0, &stat) < 0) {
error("ERROR: zip_stat_index failed for %s\n", stat.name);
logger(LL_ERROR, "zip_stat_index failed for %s\n", stat.name);
ret = -1;
continue;
}
@@ -1024,12 +1034,12 @@ int ipsw_list_contents(ipsw_archive_t ipsw, ipsw_list_cb cb, void *ctx)
uint8_t opsys;
uint32_t attributes;
if (zip_file_get_external_attributes(zip, index, 0, &opsys, &attributes) < 0) {
error("ERROR: zip_file_get_external_attributes failed for %s\n", stat.name);
logger(LL_ERROR, "zip_file_get_external_attributes failed for %s\n", stat.name);
ret = -1;
continue;
}
if (opsys != ZIP_OPSYS_UNIX) {
error("ERROR: File %s does not have UNIX attributes\n", stat.name);
logger(LL_ERROR, "File %s does not have UNIX attributes\n", stat.name);
ret = -1;
continue;
}
@@ -1079,32 +1089,32 @@ int ipsw_get_signed_firmwares(const char* product, plist_t* firmwares)
snprintf(url, sizeof(url), "https://api.ipsw.me/v4/device/%s", product);
if (download_to_buffer(url, &jdata, &jsize) < 0) {
error("ERROR: Download from %s failed.\n", url);
logger(LL_ERROR, "Download from %s failed.\n", url);
return -1;
}
plist_from_json(jdata, jsize, &dict);
free(jdata);
if (!dict || plist_get_node_type(dict) != PLIST_DICT) {
error("ERROR: Failed to parse json data.\n");
logger(LL_ERROR, "Failed to parse json data.\n");
plist_free(dict);
return -1;
}
node = plist_dict_get_item(dict, "identifier");
if (!node || plist_get_node_type(node) != PLIST_STRING) {
error("ERROR: Unexpected json data returned - missing 'identifier'\n");
logger(LL_ERROR, "Unexpected json data returned - missing 'identifier'\n");
plist_free(dict);
return -1;
}
product_type = plist_get_string_ptr(node, NULL);
if (!product_type || strcmp(product_type, product) != 0) {
error("ERROR: Unexpected json data returned - failed to read identifier\n");
logger(LL_ERROR, "Unexpected json data returned - failed to read identifier\n");
plist_free(dict);
return -1;
}
fws = plist_dict_get_item(dict, "firmwares");
if (!fws || plist_get_node_type(fws) != PLIST_ARRAY) {
error("ERROR: Unexpected json data returned - missing 'firmwares'\n");
logger(LL_ERROR, "Unexpected json data returned - missing 'firmwares'\n");
plist_free(dict);
return -1;
}
@@ -1136,14 +1146,14 @@ int ipsw_get_latest_fw(plist_t version_data, const char* product, char** fwurl,
plist_t n1 = plist_dict_get_item(version_data, "MobileDeviceSoftwareVersionsByVersion");
if (!n1) {
error("%s: ERROR: Can't find MobileDeviceSoftwareVersionsByVersion dict in version data\n", __func__);
logger(LL_ERROR, "%s: ERROR: Can't find MobileDeviceSoftwareVersionsByVersion dict in version data\n", __func__);
return -1;
}
plist_dict_iter iter = NULL;
plist_dict_new_iter(n1, &iter);
if (!iter) {
error("%s: ERROR: Can't get dict iter\n", __func__);
logger(LL_ERROR, "%s: ERROR: Can't get dict iter\n", __func__);
return -1;
}
char* key = NULL;
@@ -1164,7 +1174,7 @@ int ipsw_get_latest_fw(plist_t version_data, const char* product, char** fwurl,
free(iter);
if (major == 0) {
error("%s: ERROR: Can't find major version?!\n", __func__);
logger(LL_ERROR, "%s: ERROR: Can't find major version?!\n", __func__);
return -1;
}
@@ -1172,13 +1182,13 @@ int ipsw_get_latest_fw(plist_t version_data, const char* product, char** fwurl,
snprintf(majstr, sizeof(majstr), "%"PRIu64, (uint64_t)major);
n1 = plist_access_path(version_data, 7, "MobileDeviceSoftwareVersionsByVersion", majstr, "MobileDeviceSoftwareVersions", product, "Unknown", "Universal", "Restore");
if (!n1) {
error("%s: ERROR: Can't get Unknown/Universal/Restore node?!\n", __func__);
logger(LL_ERROR, "%s: ERROR: Can't get Unknown/Universal/Restore node?!\n", __func__);
return -1;
}
plist_t n2 = plist_dict_get_item(n1, "BuildVersion");
if (!n2 || (plist_get_node_type(n2) != PLIST_STRING)) {
error("%s: ERROR: Can't get build version node?!\n", __func__);
logger(LL_ERROR, "%s: ERROR: Can't get build version node?!\n", __func__);
return -1;
}
@@ -1187,7 +1197,7 @@ int ipsw_get_latest_fw(plist_t version_data, const char* product, char** fwurl,
n1 = plist_access_path(version_data, 5, "MobileDeviceSoftwareVersionsByVersion", majstr, "MobileDeviceSoftwareVersions", product, strval);
if (!n1) {
error("%s: ERROR: Can't get MobileDeviceSoftwareVersions/%s node?!\n", __func__, strval);
logger(LL_ERROR, "%s: ERROR: Can't get MobileDeviceSoftwareVersions/%s node?!\n", __func__, strval);
free(strval);
return -1;
}
@@ -1203,7 +1213,7 @@ int ipsw_get_latest_fw(plist_t version_data, const char* product, char** fwurl,
free(strval);
strval = NULL;
if (!n1 || (plist_dict_get_size(n1) == 0)) {
error("%s: ERROR: Can't get MobileDeviceSoftwareVersions/%s dict\n", __func__, product);
logger(LL_ERROR, "%s: ERROR: Can't get MobileDeviceSoftwareVersions/%s dict\n", __func__, product);
return -1;
}
}
@@ -1221,7 +1231,7 @@ int ipsw_get_latest_fw(plist_t version_data, const char* product, char** fwurl,
n2 = plist_access_path(n1, 2, "Restore", "FirmwareURL");
if (!n2 || (plist_get_node_type(n2) != PLIST_STRING)) {
error("%s: ERROR: Can't get FirmwareURL node\n", __func__);
logger(LL_ERROR, "%s: ERROR: Can't get FirmwareURL node\n", __func__);
return -1;
}
@@ -1254,13 +1264,23 @@ static int sha1_verify_fp(FILE* f, unsigned char* expected_sha1)
{
unsigned char tsha1[20];
char buf[8192];
size_t total = 0;
struct stat fst;
int lastprog = 0;
if (!f) return 0;
sha1_context sha1ctx;
sha1_init(&sha1ctx);
rewind(f);
fstat(fileno(f), &fst);
while (!feof(f)) {
size_t sz = fread(buf, 1, 8192, f);
sha1_update(&sha1ctx, buf, sz);
total += sz;
double p = (double)total / (double)fst.st_size;
if ((int)(p*100) > lastprog) {
set_progress('SHA1', p);
lastprog = (int)(p*100);
}
}
sha1_final(&sha1ctx, tsha1);
return (memcmp(expected_sha1, tsha1, 20) == 0) ? 1 : 0;
@@ -1270,7 +1290,7 @@ int ipsw_download_fw(const char *fwurl, unsigned char* isha1, const char* todir,
{
char* fwfn = strrchr(fwurl, '/');
if (!fwfn) {
error("ERROR: can't get local filename for firmware ipsw\n");
logger(LL_ERROR, "can't get local filename for firmware ipsw\n");
return -2;
}
fwfn++;
@@ -1288,7 +1308,7 @@ int ipsw_download_fw(const char *fwurl, unsigned char* isha1, const char* todir,
lock_info_t lockinfo;
if (lock_file(fwlock, &lockinfo) != 0) {
error("WARNING: Could not lock file '%s'\n", fwlock);
logger(LL_WARNING, "Could not lock file '%s'\n", fwlock);
}
int need_dl = 0;
@@ -1296,13 +1316,15 @@ int ipsw_download_fw(const char *fwurl, unsigned char* isha1, const char* todir,
FILE* f = fopen(fwlfn, "rb");
if (f) {
if (memcmp(zsha1, isha1, 20) != 0) {
info("Verifying '%s'...\n", fwlfn);
logger(LL_INFO, "Verifying '%s'...\n", fwlfn);
register_progress('SHA1', "Verifying");
if (sha1_verify_fp(f, isha1)) {
info("Checksum matches.\n");
logger(LL_INFO, "Checksum matches.\n");
} else {
info("Checksum does not match.\n");
logger(LL_INFO, "Checksum does not match.\n");
need_dl = 1;
}
finalize_progress('SHA1');
}
fclose(f);
} else {
@@ -1312,29 +1334,35 @@ int ipsw_download_fw(const char *fwurl, unsigned char* isha1, const char* todir,
int res = 0;
if (need_dl) {
if (strncmp(fwurl, "protected:", 10) == 0) {
error("ERROR: Can't download '%s' because it needs a purchase.\n", fwfn);
logger(LL_ERROR, "Can't download '%s' because it needs a purchase.\n", fwfn);
res = -3;
} else {
remove(fwlfn);
info("Downloading firmware (%s)\n", fwurl);
logger(LL_INFO, "Downloading firmware (%s)\n", fwurl);
download_to_file(fwurl, fwlfn, 1);
if (global_quit_flag > 0) {
logger(LL_NOTICE, "Download aborted by user\n");
return -1;
}
if (memcmp(isha1, zsha1, 20) != 0) {
info("\nVerifying '%s'...\n", fwlfn);
logger(LL_INFO, "Verifying '%s'...\n", fwlfn);
FILE* f = fopen(fwlfn, "rb");
if (f) {
register_progress('SHA1', "Verifying");
if (sha1_verify_fp(f, isha1)) {
info("Checksum matches.\n");
logger(LL_INFO, "Checksum matches.\n");
} else {
error("ERROR: File download failed (checksum mismatch).\n");
logger(LL_ERROR, "File download failed (checksum mismatch).\n");
res = -4;
}
finalize_progress('SHA1');
fclose(f);
// make sure to remove invalid files
if (res < 0)
remove(fwlfn);
} else {
error("ERROR: Can't open '%s' for checksum verification\n", fwlfn);
logger(LL_ERROR, "Can't open '%s' for checksum verification\n", fwlfn);
res = -5;
}
}
@@ -1345,7 +1373,7 @@ int ipsw_download_fw(const char *fwurl, unsigned char* isha1, const char* todir,
}
if (unlock_file(&lockinfo) != 0) {
error("WARNING: Could not unlock file '%s'\n", fwlock);
logger(LL_WARNING, "Could not unlock file '%s'\n", fwlock);
}
return res;
@@ -1359,17 +1387,17 @@ int ipsw_download_latest_fw(plist_t version_data, const char* product, const cha
*ipswfile = NULL;
if ((ipsw_get_latest_fw(version_data, product, &fwurl, isha1) < 0) || !fwurl) {
error("ERROR: can't get URL for latest firmware\n");
logger(LL_ERROR, "can't get URL for latest firmware\n");
return -1;
}
char* fwfn = strrchr(fwurl, '/');
if (!fwfn) {
error("ERROR: can't get local filename for firmware ipsw\n");
logger(LL_ERROR, "can't get local filename for firmware ipsw\n");
return -2;
}
fwfn++;
info("Latest firmware is %s\n", fwfn);
logger(LL_INFO, "Latest firmware is %s\n", fwfn);
int res = ipsw_download_fw(fwurl, isha1, todir, ipswfile);
@@ -1390,14 +1418,14 @@ ipsw_file_handle_t ipsw_file_open(ipsw_archive_t ipsw, const char* path)
int err = 0;
struct zip *zip = zip_open(ipsw->path, 0, &err);
if (zip == NULL) {
error("ERROR: zip_open: %s: %d\n", ipsw->path, err);
logger(LL_ERROR, "zip_open: %s: %d\n", ipsw->path, err);
return NULL;
}
zip_stat_t zst;
zip_int64_t zindex = zip_name_locate(zip, path, 0);
if (zindex < 0) {
error("ERROR: zip_name_locate: %s not found\n", path);
logger(LL_ERROR, "zip_name_locate: %s not found\n", path);
zip_unchange_all(zip);
zip_close(zip);
free(handle);
@@ -1405,7 +1433,7 @@ ipsw_file_handle_t ipsw_file_open(ipsw_archive_t ipsw, const char* path)
}
handle->zfile = zip_fopen_index(zip, zindex, 0);
if (handle->zfile == NULL) {
error("ERROR: zip_fopen_index: %s could not be opened\n", path);
logger(LL_ERROR, "zip_fopen_index: %s could not be opened\n", path);
zip_unchange_all(zip);
zip_close(zip);
free(handle);
@@ -1422,7 +1450,7 @@ ipsw_file_handle_t ipsw_file_open(ipsw_archive_t ipsw, const char* path)
handle->file = fopen(filepath, "rb");
free(filepath);
if (!handle->file) {
error("ERROR: fopen: %s could not be opened\n", path);
logger(LL_ERROR, "fopen: %s could not be opened\n", path);
free(handle);
return NULL;
}
@@ -1461,7 +1489,7 @@ int64_t ipsw_file_read(ipsw_file_handle_t handle, void* buffer, size_t size)
} else if (handle && handle->file) {
return fread(buffer, 1, size, handle->file);
} else {
error("ERROR: %s: Invalid file handle\n", __func__);
logger(LL_ERROR, "%s: Invalid file handle\n", __func__);
return -1;
}
}
@@ -1480,7 +1508,7 @@ int ipsw_file_seek(ipsw_file_handle_t handle, int64_t offset, int whence)
return fseeko(handle->file, offset, whence);
#endif
} else {
error("ERROR: %s: Invalid file handle\n", __func__);
logger(LL_ERROR, "%s: Invalid file handle\n", __func__);
return -1;
}
}
@@ -1496,7 +1524,7 @@ int64_t ipsw_file_tell(ipsw_file_handle_t handle)
return ftello(handle->file);
#endif
} else {
error("ERROR: %s: Invalid file handle\n", __func__);
logger(LL_ERROR, "%s: Invalid file handle\n", __func__);
return -1;
}
}
+11 -11
View File
@@ -78,7 +78,7 @@ int limera1n_exploit(struct irecv_device *device, irecv_client_t *pclient)
stack_address = 0x84033F98;
shellcode_address = 0x84023001;
} else {
error("Unsupported ChipID 0x%04x. Can't exploit with limera1n.\n", device->chip_id);
logger(LL_ERROR, "Unsupported ChipID 0x%04x. Can't exploit with limera1n.\n", device->chip_id);
return -1;
}
@@ -87,10 +87,10 @@ int limera1n_exploit(struct irecv_device *device, irecv_client_t *pclient)
irecv_client_t client = *pclient;
debug("Resetting device counters\n");
logger(LL_DEBUG, "Resetting device counters\n");
err = irecv_reset_counters(client);
if (err != IRECV_E_SUCCESS) {
error("%s\n", irecv_strerror(err));
logger(LL_ERROR, "%s\n", irecv_strerror(err));
return -1;
}
@@ -103,7 +103,7 @@ int limera1n_exploit(struct irecv_device *device, irecv_client_t *pclient)
heap[3] = stack_address;
}
debug("Sending chunk headers\n");
logger(LL_DEBUG, "Sending chunk headers\n");
irecv_usb_control_transfer(client, 0x21, 1, 0, 0, buf, 0x800, 1000);
memset(buf, 0xCC, 0x800);
@@ -111,32 +111,32 @@ int limera1n_exploit(struct irecv_device *device, irecv_client_t *pclient)
irecv_usb_control_transfer(client, 0x21, 1, 0, 0, buf, 0x800, 1000);
}
debug("Sending exploit payload\n");
logger(LL_DEBUG, "Sending exploit payload\n");
irecv_usb_control_transfer(client, 0x21, 1, 0, 0, shellcode, 0x800, 1000);
debug("Sending fake data\n");
logger(LL_DEBUG, "Sending fake data\n");
memset(buf, 0xBB, 0x800);
irecv_usb_control_transfer(client, 0xA1, 1, 0, 0, buf, 0x800, 1000);
irecv_usb_control_transfer(client, 0x21, 1, 0, 0, buf, 0x800, 10);
//debug("Executing exploit\n");
//logger(LL_DEBUG, "Executing exploit\n");
irecv_usb_control_transfer(client, 0x21, 2, 0, 0, buf, 0, 1000);
irecv_reset(client);
irecv_finish_transfer(client);
debug("Exploit sent\n");
logger(LL_DEBUG, "Exploit sent\n");
debug("Reconnecting to device\n");
logger(LL_DEBUG, "Reconnecting to device\n");
*pclient = irecv_reconnect(client, 7);
if (*pclient == NULL) {
error("Unable to reconnect\n");
logger(LL_ERROR, "Unable to reconnect\n");
return -1;
}
irecv_get_mode((*pclient), &mode);
if (mode != IRECV_K_DFU_MODE) {
error("Device reconnected in non-DFU mode\n");
logger(LL_ERROR, "Device reconnected in non-DFU mode\n");
return -1;
}
+6 -6
View File
@@ -35,7 +35,7 @@ int lock_file(const char* filename, lock_info_t* lockinfo)
#ifdef WIN32
lockinfo->fp = CreateFile(filename, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (lockinfo->fp == INVALID_HANDLE_VALUE) {
debug("ERROR: could not open or create lockfile '%s'\n", filename);
logger(LL_DEBUG, "ERROR: could not open or create lockfile '%s'\n", filename);
return -1;
}
@@ -43,7 +43,7 @@ int lock_file(const char* filename, lock_info_t* lockinfo)
lockinfo->ldata.OffsetHigh = 0;
if (!LockFileEx(lockinfo->fp, LOCKFILE_EXCLUSIVE_LOCK, 0, 1, 0, &lockinfo->ldata)) {
debug("ERROR: can't lock file, error %d\n", GetLastError());
logger(LL_DEBUG, "ERROR: can't lock file, error %d\n", GetLastError());
CloseHandle(lockinfo->fp);
lockinfo->fp = INVALID_HANDLE_VALUE;
return -1;
@@ -52,7 +52,7 @@ int lock_file(const char* filename, lock_info_t* lockinfo)
lockinfo->fp = fopen(filename, "a+");
if (!lockinfo->fp) {
debug("ERROR: could not open or create lockfile '%s'\n", filename);
logger(LL_DEBUG, "ERROR: could not open or create lockfile '%s'\n", filename);
return -1;
}
@@ -62,7 +62,7 @@ int lock_file(const char* filename, lock_info_t* lockinfo)
lockinfo->ldata.l_len = 0;
if (fcntl(fileno(lockinfo->fp), F_SETLKW, &lockinfo->ldata) < 0) {
debug("ERROR: can't lock file, error %d\n", errno);
logger(LL_DEBUG, "ERROR: can't lock file, error %d\n", errno);
fclose(lockinfo->fp);
lockinfo->fp = NULL;
return -1;
@@ -85,7 +85,7 @@ int unlock_file(lock_info_t* lockinfo)
lockinfo->ldata.OffsetHigh = 0;
if (!UnlockFileEx(lockinfo->fp, 0, 1, 0, &lockinfo->ldata)) {
debug("ERROR: can't unlock file, error %d\n", GetLastError());
logger(LL_DEBUG, "ERROR: can't unlock file, error %d\n", GetLastError());
CloseHandle(lockinfo->fp);
lockinfo->fp = INVALID_HANDLE_VALUE;
return -1;
@@ -103,7 +103,7 @@ int unlock_file(lock_info_t* lockinfo)
lockinfo->ldata.l_len = 0;
if (fcntl(fileno(lockinfo->fp), F_SETLK, &lockinfo->ldata) < 0) {
debug("ERROR: can't unlock file, error %d\n", errno);
logger(LL_DEBUG, "ERROR: can't unlock file, error %d\n", errno);
fclose(lockinfo->fp);
lockinfo->fp = NULL;
return -1;
+210
View File
@@ -0,0 +1,210 @@
/*
* log.c
*
* Copyright (c) 2024 Nikias Bassen. 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
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <time.h>
#ifdef _WIN32
#include <windows.h>
#else
#include <sys/time.h>
#endif
#include <errno.h>
#include <libimobiledevice-glue/thread.h>
#include <plist/plist.h>
#include "log.h"
static int stderr_enabled = 1;
int log_level = LL_VERBOSE;
int print_level = LL_INFO;
static void (*print_func)(int level, const char* fmt, va_list) = NULL;
const char *_level_label[6] = {
" <Error>",
"<Warning>",
" <Notice>",
" <Info>",
"<Verbose>",
" <Debug>"
};
// Reference: https://stackoverflow.com/a/2390626/1806760
// Initializer/finalizer sample for MSVC and GCC/Clang.
// 2010-2016 Joe Lowe. Released into the public domain.
#ifdef __cplusplus
#define INITIALIZER(f) \
static void f(void); \
struct f##_t_ { f##_t_(void) { f(); } }; static f##_t_ f##_; \
static void f(void)
#elif defined(_MSC_VER)
#pragma section(".CRT$XCU",read)
#define INITIALIZER2_(f,p) \
static void f(void); \
__declspec(allocate(".CRT$XCU")) void (*f##_)(void) = f; \
__pragma(comment(linker,"/include:" p #f "_")) \
static void f(void)
#ifdef _WIN64
#define INITIALIZER(f) INITIALIZER2_(f,"")
#else
#define INITIALIZER(f) INITIALIZER2_(f,"_")
#endif
#else
#define INITIALIZER(f) \
static void f(void) __attribute__((__constructor__)); \
static void f(void)
#endif
static mutex_t log_mutex;
static void logger_deinit(void)
{
mutex_destroy(&log_mutex);
}
INITIALIZER(logger_init)
{
mutex_init(&log_mutex);
atexit(logger_deinit);
}
void logger(enum loglevel level, const char *fmt, ...)
{
va_list ap;
char *fs;
if (level > log_level)
return;
mutex_lock(&log_mutex);
size_t fslen = 24 + strlen(fmt);
fs = malloc(fslen);
#ifdef _WIN32
SYSTEMTIME lt;
GetLocalTime(&lt);
snprintf(fs, 24, "%02d:%02d:%02d.%03d", lt.wHour, lt.wMinute, lt.wSecond, lt.wMilliseconds);
#else
struct timeval ts;
struct tm tp_;
struct tm *tp;
gettimeofday(&ts, NULL);
#ifdef HAVE_LOCALTIME_R
tp = localtime_r(&ts.tv_sec, &tp_);
#else
tp = localtime(&ts.tv_sec);
#endif
strftime(fs, 9, "%H:%M:%S", tp);
snprintf(fs+8, fslen-8, ".%03d %s %s", (int)(ts.tv_usec / 1000), _level_label[level], fmt);
#endif
va_start(ap, fmt);
if (print_func) {
if (stderr_enabled) {
vfprintf(stderr, fs, ap);
fflush(stderr);
}
if (level <= print_level) {
// skip the timestamp and log level string
print_func(level, fs+23, ap);
}
} else {
vprintf(fs, ap);
}
va_end(ap);
free(fs);
mutex_unlock(&log_mutex);
}
void logger_dump_hex(enum loglevel level, const void* buf, unsigned int len)
{
char *fs;
if (level > log_level)
return;
mutex_lock(&log_mutex);
fs = (char*)malloc(len * 3 + 1);
for (unsigned int i = 0; i < len; i++) {
snprintf(fs + i*3, 3, "%02x%c", ((unsigned char*)buf)[i], (i < len-1) ? ' ' : '\n');
}
if (print_func) {
if (stderr_enabled) {
fprintf(stderr, "%s", fs);
fflush(stderr);
}
if (level <= print_level) {
print_func(level, "%s", fs);
}
} else {
printf("%s", fs);
}
free(fs);
mutex_unlock(&log_mutex);
}
void logger_dump_plist(enum loglevel level, plist_t plist, int human_readable)
{
if (level > log_level)
return;
mutex_lock(&log_mutex);
plist_write_to_stream(plist, stderr_enabled ? stderr : stdout, (human_readable) ? PLIST_FORMAT_PRINT : PLIST_FORMAT_XML, PLIST_OPT_NONE);
mutex_unlock(&log_mutex);
}
int logger_set_logfile(const char* path)
{
if (!path || !strcasecmp(path, "NULL") || !strcasecmp(path, "NONE")) {
stderr_enabled = 0;
return 0;
}
stderr_enabled = 1;
if (strcmp(path, "-")) {
FILE* newf = freopen(path, "w", stderr);
if (!newf) {
logger(LL_ERROR, "Could not open logfile '%s': %s\n", path, strerror(errno));
return -1;
}
}
return 0;
}
void logger_set_print_func(void (*func)(int, const char*, va_list))
{
print_func = func;
}
+41
View File
@@ -0,0 +1,41 @@
/*
* log.h
*
* Copyright (c) 2024 Nikias Bassen. 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
*/
#ifndef LOG_H
#define LOG_H
enum loglevel {
LL_ERROR = 0,
LL_WARNING,
LL_NOTICE,
LL_INFO,
LL_VERBOSE,
LL_DEBUG
};
extern int log_level;
void logger(enum loglevel level, const char *fmt, ...) __attribute__ ((format (printf, 2, 3)));
int logger_set_logfile(const char* path);
void logger_set_print_func(void (*func)(int level, const char*, va_list));
void logger_dump_hex(enum loglevel level, const void* buf, unsigned int len);
void logger_dump_plist(enum loglevel level, plist_t plist, int human_readable);
#endif
+4 -4
View File
@@ -54,10 +54,10 @@ mbn_file* mbn_parse(unsigned char* data, unsigned int size)
// we cheat here since we don't parse the actual ELF file
mbn->parsed_size = mbn->size;
} else {
debug("DEBUG: Unknown file format passed to %s\n", __func__);
logger(LL_DEBUG, "Unknown file format passed to %s\n", __func__);
}
if (mbn->parsed_size != mbn->size) {
info("WARNING: size mismatch when parsing MBN file. Continuing anyway.\n");
logger(LL_WARNING, "Size mismatch when parsing MBN file. Continuing anyway.\n");
}
return mbn;
}
@@ -75,12 +75,12 @@ void mbn_free(mbn_file* mbn)
int mbn_update_sig_blob(mbn_file* mbn, const unsigned char* sigdata, unsigned int siglen)
{
if (!mbn) {
error("ERROR: %s: no data\n", __func__);
logger(LL_ERROR, "%s: no data\n", __func__);
return -1;
}
mbn->parsed_sig_offset = mbn->size - siglen;
if ((mbn->parsed_sig_offset + siglen) > mbn->size) {
error("ERROR: %s: signature is larger than mbn file size\n", __func__);
logger(LL_ERROR, "%s: signature is larger than mbn file size\n", __func__);
return -1;
}
+60 -56
View File
@@ -49,12 +49,12 @@ static int normal_idevice_new(struct idevicerestore_client_t* client, idevice_t*
if (client->udid) {
device_error = idevice_new(&dev, client->udid);
if (device_error != IDEVICE_E_SUCCESS) {
debug("%s: can't open device with UDID %s\n", __func__, client->udid);
logger(LL_DEBUG, "%s: can't open device with UDID %s\n", __func__, client->udid);
return -1;
}
if (lockdownd_client_new(dev, &lockdown, "idevicerestore") != LOCKDOWN_E_SUCCESS) {
error("ERROR: %s: can't connect to lockdownd on device with UDID %s\n", __func__, client->udid);
logger(LL_ERROR, "%s: can't connect to lockdownd on device with UDID %s\n", __func__, client->udid);
return -1;
}
@@ -94,12 +94,12 @@ static int normal_idevice_new(struct idevicerestore_client_t* client, idevice_t*
}
device_error = idevice_new(&dev, devices[j]);
if (device_error != IDEVICE_E_SUCCESS) {
debug("%s: can't open device with UDID %s\n", __func__, devices[j]);
logger(LL_DEBUG, "%s: can't open device with UDID %s\n", __func__, devices[j]);
continue;
}
if (lockdownd_client_new(dev, &lockdown, "idevicerestore") != LOCKDOWN_E_SUCCESS) {
error("ERROR: %s: can't connect to lockdownd on device with UDID %s\n", __func__, devices[j]);
logger(LL_ERROR, "%s: can't connect to lockdownd on device with UDID %s\n", __func__, devices[j]);
continue;
}
@@ -170,10 +170,7 @@ irecv_device_t normal_get_irecv_device(struct idevicerestore_client_t* client)
lockdown_error = lockdownd_client_new_with_handshake(device, &lockdown, "idevicerestore");
if (!(client->flags & FLAG_ERASE) && lockdown_error == LOCKDOWN_E_PAIRING_DIALOG_RESPONSE_PENDING) {
info("*** Device is not paired with this computer. Please trust this computer on the device to continue. ***\n");
if (client->flags & FLAG_DEBUG) {
idevice_set_debug_level(0);
}
show_banner("Device is not paired with this computer. Please trust this computer on the device to continue.\n");
while (!(client->flags & FLAG_QUIT)) {
lockdown_error = lockdownd_client_new_with_handshake(device, &lockdown, "idevicerestore");
if (lockdown_error != LOCKDOWN_E_PAIRING_DIALOG_RESPONSE_PENDING) {
@@ -181,9 +178,7 @@ irecv_device_t normal_get_irecv_device(struct idevicerestore_client_t* client)
}
sleep(1);
}
if (client->flags & FLAG_DEBUG) {
idevice_set_debug_level(1);
}
hide_banner();
if (client->flags & FLAG_QUIT) {
return NULL;
}
@@ -223,13 +218,13 @@ int normal_enter_recovery(struct idevicerestore_client_t* client)
device_error = idevice_new(&device, client->udid);
if (device_error != IDEVICE_E_SUCCESS) {
error("ERROR: Unable to find device\n");
logger(LL_ERROR, "Unable to find device\n");
return -1;
}
lockdown_error = lockdownd_client_new(device, &lockdown, "idevicerestore");
if (lockdown_error != LOCKDOWN_E_SUCCESS) {
error("ERROR: Unable to connect to lockdownd: %s (%d)\n", lockdownd_strerror(lockdown_error), lockdown_error);
logger(LL_ERROR, "Unable to connect to lockdownd: %s (%d)\n", lockdownd_strerror(lockdown_error), lockdown_error);
idevice_free(device);
return -1;
}
@@ -239,14 +234,14 @@ int normal_enter_recovery(struct idevicerestore_client_t* client)
lockdownd_client_free(lockdown);
lockdown = NULL;
if (LOCKDOWN_E_SUCCESS != (lockdown_error = lockdownd_client_new_with_handshake(device, &lockdown, "idevicerestore"))) {
error("ERROR: Could not connect to lockdownd: %s (%d)\n", lockdownd_strerror(lockdown_error), lockdown_error);
logger(LL_ERROR, "Could not connect to lockdownd: %s (%d)\n", lockdownd_strerror(lockdown_error), lockdown_error);
idevice_free(device);
return -1;
}
lockdown_error = lockdownd_enter_recovery(lockdown);
}
if (lockdown_error != LOCKDOWN_E_SUCCESS) {
error("ERROR: Unable to place device in recovery mode: %s (%d)\n", lockdownd_strerror(lockdown_error), lockdown_error);
logger(LL_ERROR, "Unable to place device in recovery mode: %s (%d)\n", lockdownd_strerror(lockdown_error), lockdown_error);
lockdownd_client_free(lockdown);
idevice_free(device);
return -1;
@@ -258,25 +253,25 @@ int normal_enter_recovery(struct idevicerestore_client_t* client)
device = NULL;
mutex_lock(&client->device_event_mutex);
debug("DEBUG: Waiting for device to disconnect...\n");
logger(LL_DEBUG, "Waiting for device to disconnect...\n");
cond_wait_timeout(&client->device_event_cond, &client->device_event_mutex, 60000);
if (client->mode == MODE_NORMAL || (client->flags & FLAG_QUIT)) {
mutex_unlock(&client->device_event_mutex);
error("ERROR: Failed to place device in recovery mode\n");
logger(LL_ERROR, "Failed to place device in recovery mode\n");
return -1;
}
debug("DEBUG: Waiting for device to connect in recovery mode...\n");
logger(LL_DEBUG, "Waiting for device to connect in recovery mode...\n");
cond_wait_timeout(&client->device_event_cond, &client->device_event_mutex, 60000);
if (client->mode != MODE_RECOVERY || (client->flags & FLAG_QUIT)) {
mutex_unlock(&client->device_event_mutex);
error("ERROR: Failed to enter recovery mode\n");
logger(LL_ERROR, "Failed to enter recovery mode\n");
return -1;
}
mutex_unlock(&client->device_event_mutex);
if (recovery_client_new(client) < 0) {
error("ERROR: Unable to enter recovery mode\n");
logger(LL_ERROR, "Unable to enter recovery mode\n");
return -1;
}
@@ -296,20 +291,20 @@ plist_t normal_get_lockdown_value(struct idevicerestore_client_t* client, const
device_error = idevice_new(&device, client->udid);
if (device_error != IDEVICE_E_SUCCESS) {
error("ERROR: Unable to connect to device?!\n");
logger(LL_ERROR, "Unable to connect to device?!\n");
return NULL;
}
lockdown_error = lockdownd_client_new(device, &lockdown, "idevicerestore");
if (lockdown_error != LOCKDOWN_E_SUCCESS) {
error("ERROR: Unable to connect to lockdownd\n");
logger(LL_ERROR, "Unable to connect to lockdownd\n");
idevice_free(device);
return NULL;
}
lockdown_error = lockdownd_get_value(lockdown, domain, key, &node);
if (lockdown_error != LOCKDOWN_E_SUCCESS) {
debug("ERROR: Unable to get %s-%s from lockdownd\n", domain, key);
logger(LL_DEBUG, "ERROR: Unable to get %s-%s from lockdownd\n", domain, key);
lockdownd_client_free(lockdown);
idevice_free(device);
return NULL;
@@ -328,7 +323,7 @@ static int normal_get_nonce_by_key(struct idevicerestore_client_t* client, const
plist_t nonce_node = normal_get_lockdown_value(client, NULL, key);
if (!nonce_node || plist_get_node_type(nonce_node) != PLIST_DATA) {
error("Unable to get %s\n", key);
logger(LL_ERROR, "Unable to get %s\n", key);
return -1;
}
@@ -389,12 +384,12 @@ int normal_get_firmware_preflight_info(struct idevicerestore_client_t* client, p
if (has_telephony_capability) {
node = normal_get_lockdown_value(client, NULL, "FirmwarePreflightInfo");
if (!node || plist_get_node_type(node) != PLIST_DICT) {
error("ERROR: Unable to get FirmwarePreflightInfo\n");
logger(LL_ERROR, "Unable to get FirmwarePreflightInfo\n");
return -1;
}
*preflight_info = node;
} else {
debug("DEBUG: Device does not have TelephonyCapability, no FirmwarePreflightInfo\n");
logger(LL_DEBUG, "Device does not have TelephonyCapability, no FirmwarePreflightInfo\n");
*preflight_info = NULL;
}
@@ -407,7 +402,7 @@ int normal_get_preflight_info(struct idevicerestore_client_t* client, plist_t *p
if (PLIST_IS_DICT(node)) {
*preflight_info = node;
} else {
debug("DEBUG: No PreflightInfo available.\n");
logger(LL_DEBUG, "No PreflightInfo available.\n");
*preflight_info = NULL;
}
return 0;
@@ -427,20 +422,25 @@ int normal_handle_create_stashbag(struct idevicerestore_client_t* client, plist_
device_err = idevice_new(&device, client->udid);
if (device_err != IDEVICE_E_SUCCESS) {
error("ERROR: Could not connect to device (%d)\n", device_err);
logger(LL_ERROR, "Could not connect to device (%d)\n", device_err);
return -1;
}
lerr = lockdownd_client_new_with_handshake(device, &lockdown, "idevicerestore");
if (lerr == LOCKDOWN_E_PASSWORD_PROTECTED) {
logger(LL_ERROR, "Device is locked. Unlock device and try again.\n");
idevice_free(device);
return -1;
}
if (lerr != LOCKDOWN_E_SUCCESS) {
error("ERROR: Could not connect to lockdownd (%d)\n", lerr);
logger(LL_ERROR, "Could not connect to lockdownd (%d)\n", lerr);
idevice_free(device);
return -1;
}
lerr = lockdownd_start_service(lockdown, PREBOARD_SERVICE_NAME, &service);
if (lerr == LOCKDOWN_E_PASSWORD_PROTECTED) {
info("*** Device is locked. Please unlock the device to continue. ***\n");
show_banner("Device is locked. Please unlock the device to continue.\n");
while (1) {
lerr = lockdownd_start_service(lockdown, PREBOARD_SERVICE_NAME, &service);
if (lerr != LOCKDOWN_E_PASSWORD_PROTECTED) {
@@ -451,7 +451,7 @@ int normal_handle_create_stashbag(struct idevicerestore_client_t* client, plist_
}
if (lerr != LOCKDOWN_E_SUCCESS) {
error("ERROR: Could not start preboard service (%d)\n", lerr);
logger(LL_ERROR, "Could not start preboard service (%d)\n", lerr);
lockdownd_client_free(lockdown);
idevice_free(device);
return -1;
@@ -461,14 +461,14 @@ int normal_handle_create_stashbag(struct idevicerestore_client_t* client, plist_
lockdownd_service_descriptor_free(service);
lockdownd_client_free(lockdown);
if (perr != PREBOARD_E_SUCCESS) {
error("ERROR: Could not connect to preboard service (%d)\n", perr);
logger(LL_ERROR, "Could not connect to preboard service (%d)\n", perr);
idevice_free(device);
return -1;
}
perr = preboard_create_stashbag(preboard, manifest, NULL, NULL);
if (perr != PREBOARD_E_SUCCESS) {
error("ERROR: Failed to trigger stashbag creation (%d)\n", perr);
logger(LL_ERROR, "Failed to trigger stashbag creation (%d)\n", perr);
preboard_client_free(preboard);
idevice_free(device);
return -1;
@@ -481,25 +481,25 @@ int normal_handle_create_stashbag(struct idevicerestore_client_t* client, plist_
if (perr == PREBOARD_E_TIMEOUT) {
continue;
} else if (perr != PREBOARD_E_SUCCESS) {
error("ERROR: could not receive from preboard service\n");
logger(LL_ERROR, "could not receive from preboard service\n");
break;
} else {
plist_t node;
if (plist_dict_get_bool(pl, "Skip")) {
result = 0;
info("Device does not require stashbag.\n");
logger(LL_INFO, "Device does not require stashbag.\n");
break;
}
if (plist_dict_get_bool(pl, "ShowDialog")) {
info("Device requires stashbag.\n");
printf("******************************************************************************\n"
"* Please enter your passcode on the device. The device will store a token *\n"
"* that will be used after restore to access the user data partition. This *\n"
"* prevents an 'Attempting data recovery' process occurring after reboot that *\n"
"* may take a long time to complete and will _also_ require the passcode. *\n"
"******************************************************************************\n");
logger(LL_INFO, "Device requires stashbag.\n");
show_banner(
"Please enter your passcode on the device. The device will store a token\n"
"that will be used after restore to access the user data partition. This\n"
"prevents an 'Attempting data recovery' process occurring after reboot that\n"
"may take a long time to complete and will _also_ require the passcode."
);
plist_free(pl);
continue;
}
@@ -510,13 +510,13 @@ int normal_handle_create_stashbag(struct idevicerestore_client_t* client, plist_
if (node) {
plist_get_string_val(node, &strval);
}
error("ERROR: Could not create stashbag: %s\n", (strval) ? strval : "(Unknown error)");
logger(LL_ERROR, "Could not create stashbag: %s\n", (strval) ? strval : "(Unknown error)");
free(strval);
plist_free(pl);
break;
}
if (plist_dict_get_bool(pl, "Timeout")) {
error("ERROR: Timeout while waiting for user to enter passcode.\n");
logger(LL_ERROR, "Timeout while waiting for user to enter passcode.\n");
result = -2;
plist_free(pl);
break;
@@ -525,12 +525,15 @@ int normal_handle_create_stashbag(struct idevicerestore_client_t* client, plist_
plist_free(pl);
/* hide dialog */
result = 1;
info("Stashbag created.\n");
logger(LL_INFO, "Stashbag created.\n");
break;
}
}
plist_free(pl);
}
hide_banner();
preboard_client_free(preboard);
idevice_free(device);
@@ -552,20 +555,20 @@ int normal_handle_commit_stashbag(struct idevicerestore_client_t* client, plist_
device_err = idevice_new(&device, client->udid);
if (device_err != IDEVICE_E_SUCCESS) {
error("ERROR: Could not connect to device (%d)\n", device_err);
logger(LL_ERROR, "Could not connect to device (%d)\n", device_err);
return -1;
}
lerr = lockdownd_client_new_with_handshake(device, &lockdown, "idevicerestore");
if (lerr != LOCKDOWN_E_SUCCESS) {
error("ERROR: Could not connect to lockdownd (%d)\n", lerr);
logger(LL_ERROR, "Could not connect to lockdownd (%d)\n", lerr);
idevice_free(device);
return -1;
}
lerr = lockdownd_start_service(lockdown, PREBOARD_SERVICE_NAME, &service);
if (lerr == LOCKDOWN_E_PASSWORD_PROTECTED) {
info("*** Device is locked. Please unlock the device to continue. ***\n");
show_banner("Device is locked. Please unlock the device to continue.\n");
while (1) {
lerr = lockdownd_start_service(lockdown, PREBOARD_SERVICE_NAME, &service);
if (lerr != LOCKDOWN_E_PASSWORD_PROTECTED) {
@@ -573,10 +576,11 @@ int normal_handle_commit_stashbag(struct idevicerestore_client_t* client, plist_
}
sleep(1);
}
hide_banner();
}
if (lerr != LOCKDOWN_E_SUCCESS) {
error("ERROR: Could not start preboard service (%d)\n", lerr);
logger(LL_ERROR, "Could not start preboard service (%d)\n", lerr);
lockdownd_client_free(lockdown);
idevice_free(device);
return -1;
@@ -586,14 +590,14 @@ int normal_handle_commit_stashbag(struct idevicerestore_client_t* client, plist_
lockdownd_service_descriptor_free(service);
lockdownd_client_free(lockdown);
if (perr != PREBOARD_E_SUCCESS) {
error("ERROR: Could not connect to preboard service (%d)\n", perr);
logger(LL_ERROR, "Could not connect to preboard service (%d)\n", perr);
idevice_free(device);
return -1;
}
perr = preboard_commit_stashbag(preboard, manifest, NULL, NULL);
if (perr != PREBOARD_E_SUCCESS) {
error("ERROR: Failed to trigger stashbag creation (%d)\n", perr);
logger(LL_ERROR, "Failed to trigger stashbag creation (%d)\n", perr);
preboard_client_free(preboard);
idevice_free(device);
return -1;
@@ -601,7 +605,7 @@ int normal_handle_commit_stashbag(struct idevicerestore_client_t* client, plist_
perr = preboard_receive_with_timeout(preboard, &pl, 30000);
if (perr != PREBOARD_E_SUCCESS) {
error("ERROR: could not receive from preboard service (%d)\n", perr);
logger(LL_ERROR, "could not receive from preboard service (%d)\n", perr);
} else {
plist_t node = plist_dict_get_item(pl, "Error");
if (node) {
@@ -610,14 +614,14 @@ int normal_handle_commit_stashbag(struct idevicerestore_client_t* client, plist_
if (node) {
plist_get_string_val(node, &strval);
}
error("ERROR: Could not commit stashbag: %s\n", (strval) ? strval : "(Unknown error)");
logger(LL_ERROR, "Could not commit stashbag: %s\n", (strval) ? strval : "(Unknown error)");
free(strval);
} else if (plist_dict_get_bool(pl, "StashbagCommitComplete")) {
info("Stashbag committed!\n");
logger(LL_INFO, "Stashbag committed!\n");
result = 0;
} else {
error("ERROR: Unexpected reply from preboard service\n");
debug_plist(pl);
logger(LL_ERROR, "Unexpected reply from preboard service\n");
logger_dump_plist(LL_VERBOSE, pl, 1);
}
plist_free(pl);
}
+54 -52
View File
@@ -39,14 +39,15 @@
static int recovery_progress_callback(irecv_client_t client, const irecv_event_t* event)
{
if (event->type == IRECV_PROGRESS) {
//print_progress_bar(event->progress);
set_progress('RECV', (double)(event->progress/100.0));
}
return 0;
}
void recovery_client_free(struct idevicerestore_client_t* client)
{
if(client) {
if (client) {
finalize_progress('RECV');
if (client->recovery) {
if(client->recovery->client) {
irecv_close(client->recovery->client);
@@ -68,7 +69,7 @@ int recovery_client_new(struct idevicerestore_client_t* client)
if(client->recovery == NULL) {
client->recovery = (struct recovery_client_t*)malloc(sizeof(struct recovery_client_t));
if (client->recovery == NULL) {
error("ERROR: Out of memory\n");
logger(LL_ERROR, "Out of memory\n");
return -1;
}
memset(client->recovery, 0, sizeof(struct recovery_client_t));
@@ -81,23 +82,24 @@ int recovery_client_new(struct idevicerestore_client_t* client)
}
if (i >= attempts) {
error("ERROR: Unable to connect to device in recovery mode\n");
logger(LL_ERROR, "Unable to connect to device in recovery mode\n");
return -1;
}
sleep(4);
debug("Retrying connection...\n");
logger(LL_DEBUG, "Retrying connection...\n");
}
if (client->srnm == NULL) {
const struct irecv_device_info *device_info = irecv_get_device_info(recovery);
if (device_info && device_info->srnm) {
client->srnm = strdup(device_info->srnm);
info("INFO: device serial number is %s\n", client->srnm);
logger(LL_INFO, "INFO: device serial number is %s\n", client->srnm);
}
}
irecv_event_subscribe(recovery, IRECV_PROGRESS, &recovery_progress_callback, NULL);
register_progress('RECV', "Uploading");
client->recovery->client = recovery;
return 0;
}
@@ -108,13 +110,13 @@ int recovery_set_autoboot(struct idevicerestore_client_t* client, int enable)
recovery_error = irecv_send_command(client->recovery->client, (enable) ? "setenv auto-boot true" : "setenv auto-boot false");
if (recovery_error != IRECV_E_SUCCESS) {
error("ERROR: Unable to set auto-boot environmental variable\n");
logger(LL_ERROR, "Unable to set auto-boot environmental variable\n");
return -1;
}
recovery_error = irecv_send_command(client->recovery->client, "saveenv");
if (recovery_error != IRECV_E_SUCCESS) {
error("ERROR: Unable to save environmental variable\n");
logger(LL_ERROR, "Unable to save environmental variable\n");
return -1;
}
@@ -124,7 +126,7 @@ int recovery_set_autoboot(struct idevicerestore_client_t* client, int enable)
int recovery_enter_restore(struct idevicerestore_client_t* client, plist_t build_identity)
{
if (client->build_major >= 8) {
client->restore_boot_args = strdup("rd=md0 nand-enable-reformat=1 -progress");
client->restore_boot_args = strdup("rd=md0 nand-enable-reformat=1rogress");
} else if (client->macos_variant) {
client->restore_boot_args = strdup("rd=md0 nand-enable-reformat=1 -progress -restore");
}
@@ -141,21 +143,21 @@ int recovery_enter_restore(struct idevicerestore_client_t* client, plist_t build
if (!client->image4supported) {
/* send ApTicket */
if (recovery_send_ticket(client) < 0) {
error("ERROR: Unable to send APTicket\n");
logger(LL_ERROR, "Unable to send APTicket\n");
return -1;
}
}
}
info("Recovery Mode Environment:\n");
logger(LL_INFO, "Recovery Mode Environment:\n");
char* value = NULL;
irecv_getenv(client->recovery->client, "build-version", &value);
info("iBoot build-version=%s\n", (value) ? value : "(unknown)");
logger(LL_INFO, "iBoot build-version=%s\n", (value) ? value : "(unknown)");
free(value);
value = NULL;
irecv_getenv(client->recovery->client, "build-style", &value);
info("iBoot build-style=%s\n", (value) ? value : "(unknown)");
logger(LL_INFO, "iBoot build-style=%s\n", (value) ? value : "(unknown)");
free(value);
value = NULL;
@@ -165,11 +167,11 @@ int recovery_enter_restore(struct idevicerestore_client_t* client, plist_t build
boot_stage = strtoul(value, NULL, 0);
}
if (boot_stage > 0) {
info("iBoot boot-stage=%s\n", value);
logger(LL_INFO, "iBoot boot-stage=%s\n", value);
free(value);
value = NULL;
if (boot_stage != 2) {
error("ERROR: iBoot should be at boot stage 2, continuing anyway...\n");
logger(LL_ERROR, "iBoot should be at boot stage 2, continuing anyway...\n");
}
}
@@ -179,12 +181,12 @@ int recovery_enter_restore(struct idevicerestore_client_t* client, plist_t build
radio_error = strtoul(value, NULL, 0);
}
if (radio_error > 0) {
info("radio-error=%s\n", value);
logger(LL_INFO, "radio-error=%s\n", value);
free(value);
value = NULL;
irecv_getenv(client->recovery->client, "radio-error-string", &value);
if (value) {
info("radio-error-string=%s\n", value);
logger(LL_INFO, "radio-error-string=%s\n", value);
free(value);
value = NULL;
}
@@ -196,32 +198,32 @@ int recovery_enter_restore(struct idevicerestore_client_t* client, plist_t build
/* send logo and show it */
if (recovery_send_applelogo(client, build_identity) < 0) {
error("ERROR: Unable to send AppleLogo\n");
logger(LL_ERROR, "Unable to send AppleLogo\n");
return -1;
}
/* send components loaded by iBoot */
if (recovery_send_loaded_by_iboot(client, build_identity) < 0) {
error("ERROR: Unable to send components supposed to be loaded by iBoot\n");
logger(LL_ERROR, "Unable to send components supposed to be loaded by iBoot\n");
return -1;
}
/* send ramdisk and run it */
if (recovery_send_ramdisk(client, build_identity) < 0) {
error("ERROR: Unable to send Ramdisk\n");
logger(LL_ERROR, "Unable to send Ramdisk\n");
return -1;
}
/* send devicetree and load it */
if (recovery_send_component_and_command(client, build_identity, "RestoreDeviceTree", "devicetree") < 0) {
error("ERROR: Unable to send DeviceTree\n");
logger(LL_ERROR, "Unable to send DeviceTree\n");
return -1;
}
if (build_identity_has_component(build_identity, "RestoreSEP")) {
/* send rsepfirmware and load it */
if (recovery_send_component_and_command(client, build_identity, "RestoreSEP", "rsepfirmware") < 0) {
error("ERROR: Unable to send RestoreSEP\n");
logger(LL_ERROR, "Unable to send RestoreSEP\n");
return -1;
}
}
@@ -229,15 +231,15 @@ int recovery_enter_restore(struct idevicerestore_client_t* client, plist_t build
mutex_lock(&client->device_event_mutex);
if (recovery_send_kernelcache(client, build_identity) < 0) {
mutex_unlock(&client->device_event_mutex);
error("ERROR: Unable to send KernelCache\n");
logger(LL_ERROR, "Unable to send KernelCache\n");
return -1;
}
debug("DEBUG: Waiting for device to disconnect...\n");
logger(LL_DEBUG, "Waiting for device to disconnect...\n");
cond_wait_timeout(&client->device_event_cond, &client->device_event_mutex, 30000);
if (client->mode == MODE_RECOVERY || (client->flags & FLAG_QUIT)) {
mutex_unlock(&client->device_event_mutex);
error("ERROR: Failed to place device in restore mode\n");
logger(LL_ERROR, "Failed to place device in restore mode\n");
return -1;
}
mutex_unlock(&client->device_event_mutex);
@@ -248,28 +250,28 @@ int recovery_enter_restore(struct idevicerestore_client_t* client, plist_t build
int recovery_send_ticket(struct idevicerestore_client_t* client)
{
if (!client->tss) {
error("ERROR: ApTicket requested but no TSS present\n");
logger(LL_ERROR, "ApTicket requested but no TSS present\n");
return -1;
}
unsigned char* data = NULL;
uint32_t size = 0;
if (tss_response_get_ap_ticket(client->tss, &data, &size) < 0) {
error("ERROR: Unable to get ApTicket from TSS request\n");
logger(LL_ERROR, "Unable to get ApTicket from TSS request\n");
return -1;
}
info("Sending APTicket (%d bytes)\n", size);
logger(LL_INFO, "Sending APTicket (%d bytes)\n", size);
irecv_error_t err = irecv_send_buffer(client->recovery->client, data, size, 0);
free(data);
if (err != IRECV_E_SUCCESS) {
error("ERROR: Unable to send APTicket: %s\n", irecv_strerror(err));
logger(LL_ERROR, "Unable to send APTicket: %s\n", irecv_strerror(err));
return -1;
}
err = irecv_send_command(client->recovery->client, "ticket");
if (err != IRECV_E_SUCCESS) {
error("ERROR: Unable to send ticket command\n");
logger(LL_ERROR, "Unable to send ticket command\n");
return -1;
}
@@ -285,12 +287,12 @@ int recovery_send_component(struct idevicerestore_client_t* client, plist_t buil
if (client->tss) {
if (tss_response_get_path_by_entry(client->tss, component, &path) < 0) {
debug("NOTE: No path for component %s in TSS, will fetch from build_identity\n", component);
logger(LL_DEBUG, "No path for component %s in TSS, will fetch from build_identity\n", component);
}
}
if (!path) {
if (build_identity_get_component_path(build_identity, component, &path) < 0) {
error("ERROR: Unable to get path for component '%s'\n", component);
logger(LL_ERROR, "Unable to get path for component '%s'\n", component);
free(path);
return -1;
}
@@ -301,24 +303,24 @@ int recovery_send_component(struct idevicerestore_client_t* client, plist_t buil
int ret = extract_component(client->ipsw, path, &component_data, &component_size);
free(path);
if (ret < 0) {
error("ERROR: Unable to extract component: %s\n", component);
logger(LL_ERROR, "Unable to extract component: %s\n", component);
return -1;
}
ret = personalize_component(client, component, component_data, component_size, client->tss, &data, &size);
free(component_data);
if (ret < 0) {
error("ERROR: Unable to get personalized component: %s\n", component);
logger(LL_ERROR, "Unable to get personalized component: %s\n", component);
return -1;
}
info("Sending %s (%d bytes)...\n", component, size);
logger(LL_INFO, "Sending %s (%d bytes)...\n", component, size);
// FIXME: Did I do this right????
err = irecv_send_buffer(client->recovery->client, data, size, 0);
free(data);
if (err != IRECV_E_SUCCESS) {
error("ERROR: Unable to send %s component: %s\n", component, irecv_strerror(err));
logger(LL_ERROR, "Unable to send %s component: %s\n", component, irecv_strerror(err));
return -1;
}
@@ -330,13 +332,13 @@ int recovery_send_component_and_command(struct idevicerestore_client_t* client,
irecv_error_t recovery_error = IRECV_E_SUCCESS;
if (recovery_send_component(client, build_identity, component) < 0) {
error("ERROR: Unable to send %s to device.\n", component);
logger(LL_ERROR, "Unable to send %s to device.\n", component);
return -1;
}
recovery_error = irecv_send_command(client->recovery->client, command);
if (recovery_error != IRECV_E_SUCCESS) {
error("ERROR: Unable to execute %s\n", component);
logger(LL_ERROR, "Unable to execute %s\n", component);
return -1;
}
@@ -355,13 +357,13 @@ int recovery_send_ibec(struct idevicerestore_client_t* client, plist_t build_ide
}
if (recovery_send_component(client, build_identity, component) < 0) {
error("ERROR: Unable to send %s to device.\n", component);
logger(LL_ERROR, "Unable to send %s to device.\n", component);
return -1;
}
recovery_error = irecv_send_command_breq(client->recovery->client, "go", 1);
if (recovery_error != IRECV_E_SUCCESS) {
error("ERROR: Unable to execute %s\n", component);
logger(LL_ERROR, "Unable to execute %s\n", component);
return -1;
}
irecv_usb_control_transfer(client->recovery->client, 0x21, 1, 0, 0, 0, 0, 5000);
@@ -378,7 +380,7 @@ int recovery_send_applelogo(struct idevicerestore_client_t* client, plist_t buil
return 0;
}
info("Sending %s...\n", component);
logger(LL_INFO, "Sending %s...\n", component);
if (client->recovery == NULL) {
if (recovery_client_new(client) < 0) {
return -1;
@@ -386,19 +388,19 @@ int recovery_send_applelogo(struct idevicerestore_client_t* client, plist_t buil
}
if (recovery_send_component(client, build_identity, component) < 0) {
error("ERROR: Unable to send %s to device.\n", component);
logger(LL_ERROR, "Unable to send %s to device.\n", component);
return -1;
}
recovery_error = irecv_send_command(client->recovery->client, "setpicture 4");
if (recovery_error != IRECV_E_SUCCESS) {
error("ERROR: Unable to set %s\n", component);
logger(LL_ERROR, "Unable to set %s\n", component);
return -1;
}
recovery_error = irecv_send_command(client->recovery->client, "bgcolor 0 0 0");
if (recovery_error != IRECV_E_SUCCESS) {
error("ERROR: Unable to display %s\n", component);
logger(LL_ERROR, "Unable to display %s\n", component);
return -1;
}
@@ -415,7 +417,7 @@ int recovery_send_loaded_by_iboot(struct idevicerestore_client_t* client, plist_
plist_t manifest_node = plist_dict_get_item(build_identity, "Manifest");
if (!manifest_node || plist_get_node_type(manifest_node) != PLIST_DICT) {
error("ERROR: Unable to find manifest node\n");
logger(LL_ERROR, "Unable to find manifest node\n");
return -1;
}
@@ -439,9 +441,9 @@ int recovery_send_loaded_by_iboot(struct idevicerestore_client_t* client, plist_
uint8_t b = 0;
plist_get_bool_val(iboot_node, &b);
if (b) {
debug("DEBUG: %s is loaded by iBoot.\n", key);
logger(LL_DEBUG, "%s is loaded by iBoot.\n", key);
if (recovery_send_component_and_command(client, build_identity, key, "firmware") < 0) {
error("ERROR: Unable to send component '%s' to device.\n", key);
logger(LL_ERROR, "Unable to send component '%s' to device.\n", key);
err++;
}
}
@@ -466,12 +468,12 @@ int recovery_send_ramdisk(struct idevicerestore_client_t* client, plist_t build_
char* value = NULL;
irecv_getenv(client->recovery->client, "ramdisk-size", &value);
info("ramdisk-size=%s\n", (value ? value : "(unknown)"));
logger(LL_INFO, "ramdisk-size=%s\n", (value ? value : "(unknown)"));
free(value);
value = NULL;
if (recovery_send_component(client, build_identity, component) < 0) {
error("ERROR: Unable to send %s to device.\n", component);
logger(LL_ERROR, "Unable to send %s to device.\n", component);
return -1;
}
@@ -479,7 +481,7 @@ int recovery_send_ramdisk(struct idevicerestore_client_t* client, plist_t build_
recovery_error = irecv_send_command(client->recovery->client, "ramdisk");
if (recovery_error != IRECV_E_SUCCESS) {
error("ERROR: Unable to execute %s\n", component);
logger(LL_ERROR, "Unable to execute %s\n", component);
return -1;
}
@@ -500,7 +502,7 @@ int recovery_send_kernelcache(struct idevicerestore_client_t* client, plist_t bu
}
if (recovery_send_component(client, build_identity, component) < 0) {
error("ERROR: Unable to send %s to device.\n", component);
logger(LL_ERROR, "Unable to send %s to device.\n", component);
return -1;
}
@@ -515,7 +517,7 @@ int recovery_send_kernelcache(struct idevicerestore_client_t* client, plist_t bu
recovery_error = irecv_send_command_breq(client->recovery->client, "bootx", 1);
if (recovery_error != IRECV_E_SUCCESS) {
error("ERROR: Unable to execute %s\n", component);
logger(LL_ERROR, "Unable to execute %s\n", component);
return -1;
}
+558 -544
View File
File diff suppressed because it is too large Load Diff