summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Martin Szulecki2013-09-27 02:22:56 +0200
committerGravatar Martin Szulecki2013-09-27 02:22:56 +0200
commit0e2bfbd3450096ae9e4c22e18fb169429c25d1f4 (patch)
tree46e851fc0d1ff93b445ef775796039012491590d
parentc84fb716cd998118c95fb59a8ba4d3e26a673749 (diff)
downloadlibirecovery-0e2bfbd3450096ae9e4c22e18fb169429c25d1f4.tar.gz
libirecovery-0e2bfbd3450096ae9e4c22e18fb169429c25d1f4.tar.bz2
irecovery: Update code style, add "show mode" and "normal mode reboot" commands
-rw-r--r--tools/irecovery.c286
1 files changed, 191 insertions, 95 deletions
diff --git a/tools/irecovery.c b/tools/irecovery.c
index effd3fb..12f05b7 100644
--- a/tools/irecovery.c
+++ b/tools/irecovery.c
@@ -41,7 +41,9 @@ enum {
41 kSendCommand, 41 kSendCommand,
42 kSendFile, 42 kSendFile,
43 kSendExploit, 43 kSendExploit,
44 kSendScript 44 kSendScript,
45 kShowMode,
46 kRebootToNormalMode
45}; 47};
46 48
47static unsigned int quit = 0; 49static unsigned int quit = 0;
@@ -255,19 +257,51 @@ void print_progress_bar(double progress) {
255 } 257 }
256} 258}
257 259
258static void print_usage() { 260static void buffer_read_from_filename(const char *filename, char **buffer, uint64_t *length) {
259 printf("iRecovery - iDevice Recovery Utility\n"); 261 FILE *f;
260 printf("Usage: irecovery [args]\n"); 262 uint64_t size;
261 printf("\t-i <ecid>\tTarget specific device by its hexadecimal ECID\n"); 263
262 printf("\t-v\t\tStart irecovery in verbose mode.\n"); 264 *length = 0;
263 printf("\t-c <cmd>\tSend command to client.\n"); 265
264 printf("\t-f <file>\tSend file to client.\n"); 266 f = fopen(filename, "rb");
265 printf("\t-k [payload]\tSend usb exploit to client.\n"); 267 if (!f) {
266 printf("\t-h\t\tShow this help.\n"); 268 return;
267 printf("\t-r\t\tReset client.\n"); 269 }
268 printf("\t-s\t\tStart interactive shell.\n"); 270
269 printf("\t-e <script>\tExecutes recovery shell script.\n"); 271 fseek(f, 0, SEEK_END);
270 exit(1); 272 size = ftell(f);
273 rewind(f);
274
275 if (size == 0) {
276 fclose(f);
277 return;
278 }
279
280 *buffer = (char*)malloc(sizeof(char)*(size+1));
281 fread(*buffer, sizeof(char), size, f);
282 fclose(f);
283
284 *length = size;
285}
286
287static void print_usage(int argc, char **argv) {
288 char *name = NULL;
289 name = strrchr(argv[0], '/');
290 printf("Usage: %s [OPTIONS]\n", (name ? name + 1: argv[0]));
291 printf("Interact with a iBSS/iBoot iOS device in DFU or recovery mode.\n\n");
292 printf("options:\n");
293 printf(" -i ECID\tconnect to specific device by its hexadecimal ECID\n");
294 printf(" -c CMD\trun CMD on device\n");
295 printf(" -m\t\tprint current device mode\n");
296 printf(" -f FILE\tsend file to device\n");
297 printf(" -k FILE\tsend limera1in usb exploit payload from FILE\n");
298 printf(" -r\t\treset client\n");
299 printf(" -n\t\treboot device into normal mode (exit recovery loop)\n");
300 printf(" -e FILE\texecutes recovery script from FILE\n");
301 printf(" -s\t\tstart an interactive shell\n");
302 printf(" -v\t\tenable verbose output, repeat for higher verbosity\n");
303 printf(" -h\t\tprints this usage information\n");
304 printf("\n");
271} 305}
272 306
273int main(int argc, char* argv[]) { 307int main(int argc, char* argv[]) {
@@ -275,67 +309,81 @@ int main(int argc, char* argv[]) {
275 int opt = 0; 309 int opt = 0;
276 int action = 0; 310 int action = 0;
277 unsigned long long ecid = 0; 311 unsigned long long ecid = 0;
312 int mode = -1;
278 char* argument = NULL; 313 char* argument = NULL;
279 irecv_error_t error = 0; 314 irecv_error_t error = 0;
280 315
281 if (argc == 1) 316 char* buffer = NULL;
282 print_usage(); 317 uint64_t buffer_length = 0;
283 318
284 while ((opt = getopt(argc, argv, "i:vhrsc:f:e:k::")) > 0) { 319 if (argc == 1) {
320 print_usage(argc, argv);
321 return 0;
322 }
323
324 while ((opt = getopt(argc, argv, "i:vhrsmnc:f:e:k::")) > 0) {
285 switch (opt) { 325 switch (opt) {
286 case 'i': 326 case 'i':
287 if (optarg) { 327 if (optarg) {
288 char* tail = NULL; 328 char* tail = NULL;
289 ecid = strtoull(optarg, &tail, 16); 329 ecid = strtoull(optarg, &tail, 16);
290 if (tail && (tail[0] != '\0')) { 330 if (tail && (tail[0] != '\0')) {
291 ecid = 0; 331 ecid = 0;
292 } 332 }
293 if (ecid == 0) { 333 if (ecid == 0) {
294 fprintf(stderr, "ERROR: Could not parse ECID from argument '%s'\n", optarg); 334 fprintf(stderr, "ERROR: Could not parse ECID from argument '%s'\n", optarg);
295 return -1; 335 return -1;
336 }
296 } 337 }
297 } 338 break;
298 break;
299 339
300 case 'v': 340 case 'v':
301 verbose += 1; 341 verbose += 1;
302 break; 342 break;
303 343
304 case 'h': 344 case 'h':
305 print_usage(); 345 print_usage(argc, argv);
306 break; 346 return 0;
307 347
308 case 'r': 348 case 'm':
309 action = kResetDevice; 349 action = kShowMode;
310 break; 350 break;
311 351
312 case 's': 352 case 'n':
313 action = kStartShell; 353 action = kRebootToNormalMode;
314 break; 354 break;
315 355
316 case 'f': 356 case 'r':
317 action = kSendFile; 357 action = kResetDevice;
318 argument = optarg; 358 break;
319 break;
320 359
321 case 'c': 360 case 's':
322 action = kSendCommand; 361 action = kStartShell;
323 argument = optarg; 362 break;
324 break;
325 363
326 case 'k': 364 case 'f':
327 action = kSendExploit; 365 action = kSendFile;
328 argument = optarg; 366 argument = optarg;
329 break; 367 break;
330 368
331 case 'e': 369 case 'c':
332 action = kSendScript; 370 action = kSendCommand;
333 argument = optarg; 371 argument = optarg;
334 break; 372 break;
335 373
336 default: 374 case 'k':
337 fprintf(stderr, "Unknown argument\n"); 375 action = kSendExploit;
338 return -1; 376 argument = optarg;
377 break;
378
379 case 'e':
380 action = kSendScript;
381 argument = optarg;
382 break;
383
384 default:
385 fprintf(stderr, "Unknown argument\n");
386 return -1;
339 } 387 }
340 } 388 }
341 389
@@ -363,48 +411,96 @@ int main(int argc, char* argv[]) {
363 debug("Connected to %s, model %s, cpid 0x%04x, bdid 0x%02x\n", device->product_type, device->hardware_model, device->chip_id, device->board_id); 411 debug("Connected to %s, model %s, cpid 0x%04x, bdid 0x%02x\n", device->product_type, device->hardware_model, device->chip_id, device->board_id);
364 412
365 switch (action) { 413 switch (action) {
366 case kResetDevice: 414 case kResetDevice:
367 irecv_reset(client); 415 irecv_reset(client);
368 break; 416 break;
369 417
370 case kSendFile: 418 case kSendFile:
371 irecv_event_subscribe(client, IRECV_PROGRESS, &progress_cb, NULL);
372 error = irecv_send_file(client, argument, 1);
373 debug("%s\n", irecv_strerror(error));
374 break;
375
376 case kSendCommand:
377 error = irecv_send_command(client, argument);
378 debug("%s\n", irecv_strerror(error));
379 break;
380
381 case kSendExploit:
382 if (argument != NULL) {
383 irecv_event_subscribe(client, IRECV_PROGRESS, &progress_cb, NULL); 419 irecv_event_subscribe(client, IRECV_PROGRESS, &progress_cb, NULL);
384 error = irecv_send_file(client, argument, 0); 420 error = irecv_send_file(client, argument, 1);
421 debug("%s\n", irecv_strerror(error));
422 break;
423
424 case kSendCommand:
425 error = irecv_send_command(client, argument);
426 debug("%s\n", irecv_strerror(error));
427 break;
428
429 case kSendExploit:
430 if (argument != NULL) {
431 irecv_event_subscribe(client, IRECV_PROGRESS, &progress_cb, NULL);
432 error = irecv_send_file(client, argument, 0);
433 if (error != IRECV_E_SUCCESS) {
434 debug("%s\n", irecv_strerror(error));
435 break;
436 }
437 }
438 error = irecv_trigger_limera1n_exploit(client);
439 debug("%s\n", irecv_strerror(error));
440 break;
441
442 case kStartShell:
443 init_shell(client);
444 break;
445
446 case kSendScript:
447 buffer_read_from_filename(argument, &buffer, &buffer_length);
448 buffer[buffer_length] = '\0';
449
450 error = irecv_execute_script(client, buffer);
451 if(error != IRECV_E_SUCCESS) {
452 debug("%s\n", irecv_strerror(error));
453 }
454
455 if (buffer)
456 free(buffer);
457
458 break;
459
460 case kShowMode:
461 irecv_get_mode(client, &mode);
462 switch (mode) {
463 case IRECV_K_RECOVERY_MODE_1:
464 case IRECV_K_RECOVERY_MODE_2:
465 case IRECV_K_RECOVERY_MODE_3:
466 case IRECV_K_RECOVERY_MODE_4:
467 printf("Recovery Mode\n");
468 break;
469 case IRECV_K_DFU_MODE:
470 printf("DFU Mode\n");
471 break;
472 case IRECV_K_WTF_MODE:
473 printf("WTF Mode\n");
474 break;
475 default:
476 printf("Unknown Mode\n");
477 break;
478 }
479 break;
480
481 case kRebootToNormalMode:
482 error = irecv_setenv(client, "auto-boot", "true");
385 if (error != IRECV_E_SUCCESS) { 483 if (error != IRECV_E_SUCCESS) {
386 debug("%s\n", irecv_strerror(error)); 484 debug("%s\n", irecv_strerror(error));
387 break; 485 break;
388 } 486 }
389 }
390 error = irecv_trigger_limera1n_exploit(client);
391 debug("%s\n", irecv_strerror(error));
392 break;
393 487
394 case kStartShell: 488 error = irecv_saveenv(client);
395 init_shell(client); 489 if (error != IRECV_E_SUCCESS) {
396 break; 490 debug("%s\n", irecv_strerror(error));
397 491 break;
398 case kSendScript: 492 }
399 error = irecv_execute_script(client, argument);
400 if(error != IRECV_E_SUCCESS) {
401 debug("%s\n", irecv_strerror(error));
402 }
403 break;
404 493
405 default: 494 error = irecv_reboot(client);
406 fprintf(stderr, "Unknown action\n"); 495 if (error != IRECV_E_SUCCESS) {
407 break; 496 debug("%s\n", irecv_strerror(error));
497 } else {
498 debug("%s\n", irecv_strerror(error));
499 }
500 break;
501 default:
502 fprintf(stderr, "Unknown action\n");
503 break;
408 } 504 }
409 505
410 irecv_close(client); 506 irecv_close(client);