diff --git a/Makefile b/Makefile index 670fcc8..e33e21d 100644 --- a/Makefile +++ b/Makefile @@ -14,14 +14,20 @@ payloads: name=$$(basename "$$file"); \ name=$${name%.*}; \ echo " XXD $$file"; \ - xxd -i "$$file" > "src/gen/payloads/$$name.h"; \ + xxd -i "$$file" \ + | sed 's/unsigned char/static const unsigned char/g' \ + | sed 's/unsigned int/static const size_t/g' \ + > "src/gen/payloads/$$name.h"; \ done @for file in images/*; do \ name=$$(basename "$$file"); \ name=$${name%.*}; \ echo " XXD $$file"; \ - xxd -i "$$file" > "src/gen/images/$$name.h"; \ + xxd -i "$$file" \ + | sed 's/unsigned char/static const unsigned char/g' \ + | sed 's/unsigned int/static const size_t/g' \ + > "src/gen/images/$$name.h"; \ done xxd -i -n "DFUHelperDeviceInfo" resources/DFUHelperDeviceInfo.json > src/gen/DFUHelperDeviceInfo.h diff --git a/src/globals.c b/src/globals.c new file mode 100644 index 0000000..9eaccc8 --- /dev/null +++ b/src/globals.c @@ -0,0 +1,73 @@ +#include "globals.h" + +#include +#include +#include +#include +#include +#include + +#include "gen/payloads/binpack.h" +#include "gen/payloads/ramdisk.h" +#include "gen/payloads/Pongo.h" +#include "gen/payloads/checkra1n-kpf-pongo.h" + +uint64_t palerain_flags = 0; +char boot_args[0x270] = { '\0' }; + +payload_t g_payload_overlay = { + .data = payloads_binpack_dmg, + .data_len = payloads_binpack_dmg_len, +}; + +payload_t g_payload_ramdisk = { + .data = payloads_ramdisk_dmg, + .data_len = payloads_ramdisk_dmg_len, +}; + +payload_t g_payload_pongo = { + .data = payloads_Pongo_bin, + .data_len = payloads_Pongo_bin_len, +}; + +payload_t g_payload_kpf = { + .data = payloads_checkra1n_kpf_pongo, + .data_len = payloads_checkra1n_kpf_pongo_len, +}; + +bool override_payload_from_file(const char *path, payload_t *out) +{ + FILE *f = fopen(path, "rb"); + if (!f) return false; + + if (fseek(f, 0, SEEK_END) != 0) { + fclose(f); + return false; + } + + long len = ftell(f); + if (len <= 0) { + fclose(f); + return false; + } + rewind(f); + + void *buf = malloc((size_t)len); + if (!buf) { + fclose(f); + return false; + } + + if (fread(buf, 1, (size_t)len, f) != (size_t)len) { + free(buf); + fclose(f); + return false; + } + + fclose(f); + + out->data = buf; + out->data_len = (size_t)len; + + return true; +} diff --git a/src/globals.h b/src/globals.h new file mode 100644 index 0000000..563e4e6 --- /dev/null +++ b/src/globals.h @@ -0,0 +1,31 @@ +#ifndef GLOBALS_H +#define GLOBALS_H + +#include +#include +#include + +extern uint64_t palerain_flags; +extern char boot_args[0x270]; + +typedef struct { + const uint8_t *data; + size_t data_len; +} payload_t; + +extern payload_t g_payload_overlay; +extern payload_t g_payload_ramdisk; +extern payload_t g_payload_pongo; +extern payload_t g_payload_kpf; + +#ifdef __cplusplus +extern "C" { +#endif + +bool override_payload_from_file(const char *path, payload_t *out); + +#ifdef __cplusplus +} +#endif + +#endif // GLOBALS_H \ No newline at end of file diff --git a/src/m8/checkm8.c b/src/m8/checkm8.c index 310699f..79645a9 100644 --- a/src/m8/checkm8.c +++ b/src/m8/checkm8.c @@ -152,7 +152,7 @@ bool checkm8_stage_spray(const usb_handle_t *handle, struct DeviceConfiguration bool checkm8_stage_patch(const usb_handle_t *handle, struct DeviceConfiguration *deviceConfig, struct PayloadConfiguration *payloadConfig) { size_t i, data_sz, packet_sz; - uint8_t *payload = NULL; + const uint8_t *payload = NULL; uint8_t *data; transfer_ret_t transfer_ret; bool ret = false; diff --git a/src/m8/payload.c b/src/m8/payload.c index 475d2fb..dd32323 100644 --- a/src/m8/payload.c +++ b/src/m8/payload.c @@ -5,12 +5,6 @@ #include "../utils.h" -extern uint8_t payloads_yolo_s8000_bin[], payloads_yolo_s8001_bin[], payloads_yolo_s8003_bin[], payloads_yolo_t7000_bin[], payloads_yolo_t7001_bin[], payloads_yolo_t8010_bin[], payloads_yolo_t8011_bin[], payloads_yolo_t8015_bin[]; -extern unsigned payloads_yolo_s8000_bin_len, payloads_yolo_s8001_bin_len, payloads_yolo_s8003_bin_len, payloads_yolo_t7000_bin_len, payloads_yolo_t7001_bin_len, payloads_yolo_t8010_bin_len, payloads_yolo_t8011_bin_len, payloads_yolo_t8015_bin_len; - -extern uint8_t payloads_Pongo_bin[], payloads_shellcode_bin[]; -extern unsigned payloads_Pongo_bin_len, payloads_shellcode_bin_len; - #include "../gen/payloads/yolo_s8000.h" #include "../gen/payloads/yolo_s8001.h" #include "../gen/payloads/yolo_s8003.h" @@ -232,9 +226,20 @@ bool checkm8_find_payload_configuration_for_cpid( return foundMatchingConfiguration; } +static const yolo_payload_t yolo_payloads[] = { + {0x8015, payloads_yolo_t8015_bin, payloads_yolo_t8015_bin_len}, + {0x8011, payloads_yolo_t8011_bin, payloads_yolo_t8011_bin_len}, + {0x8010, payloads_yolo_t8010_bin, payloads_yolo_t8010_bin_len}, + {0x8003, payloads_yolo_s8003_bin, payloads_yolo_s8003_bin_len}, + {0x8001, payloads_yolo_s8001_bin, payloads_yolo_s8001_bin_len}, + {0x8000, payloads_yolo_s8000_bin, payloads_yolo_s8000_bin_len}, + {0x7001, payloads_yolo_t7001_bin, payloads_yolo_t7001_bin_len}, + {0x7000, payloads_yolo_t7000_bin, payloads_yolo_t7000_bin_len}, +}; + void create_pongo_payload_for_device( uint16_t cpid, - uint8_t **payload, + const uint8_t **payload, size_t *payloadSize) { LOG_VERBOSE("Preparing YoloDFU payload for CPID 0x%x.", cpid); @@ -242,41 +247,15 @@ void create_pongo_payload_for_device( *payload = NULL; *payloadSize = 0; - switch (cpid) { - case 0x8015: - *payloadSize = payloads_yolo_t8015_bin_len; - *payload = payloads_yolo_t8015_bin; - break; - case 0x8011: - *payloadSize = payloads_yolo_t8011_bin_len; - *payload = payloads_yolo_t8011_bin; - break; - case 0x8010: - *payloadSize = payloads_yolo_t8010_bin_len; - *payload = payloads_yolo_t8010_bin; - break; - case 0x8003: - *payloadSize = payloads_yolo_s8003_bin_len; - *payload = payloads_yolo_s8003_bin; - break; - case 0x8001: - *payloadSize = payloads_yolo_s8001_bin_len; - *payload = payloads_yolo_s8001_bin; - break; - case 0x8000: - *payloadSize = payloads_yolo_s8000_bin_len; - *payload = payloads_yolo_s8000_bin; - break; - case 0x7001: - *payloadSize = payloads_yolo_t7001_bin_len; - *payload = payloads_yolo_t7001_bin; - break; - case 0x7000: - *payloadSize = payloads_yolo_t7000_bin_len; - *payload = payloads_yolo_t7000_bin; - break; - default: - LOG("Failed to prepare payload for device with CPID 0x%x.", cpid); - break; + size_t count = sizeof(yolo_payloads) / sizeof(yolo_payloads[0]); + + for (size_t i = 0; i < count; i++) { + if (yolo_payloads[i].cpid == cpid) { + *payload = yolo_payloads[i].data; + *payloadSize = yolo_payloads[i].len; + return; + } } -} + + LOG("Failed to prepare payload for device with CPID 0x%x.", cpid); +} \ No newline at end of file diff --git a/src/m8/payload.h b/src/m8/payload.h index 4393b75..a561329 100644 --- a/src/m8/payload.h +++ b/src/m8/payload.h @@ -38,8 +38,14 @@ struct PayloadConfiguration { uint32_t payload_dest_armv7; }; +typedef struct { + uint16_t cpid; + const uint8_t *data; + size_t len; +} yolo_payload_t; + bool checkm8_find_device_configuration_for_cpid(int cpid, struct DeviceConfiguration *config); bool checkm8_find_payload_configuration_for_cpid(int cpid, struct PayloadConfiguration *config); -void create_pongo_payload_for_device(uint16_t cpid, uint8_t **payload, size_t *payloadSize); +void create_pongo_payload_for_device(uint16_t cpid, const uint8_t **payload, size_t *payloadSize); #endif // PAYLOAD_H diff --git a/src/m8/run.c b/src/m8/run.c index 3d7ee99..8bfb9fe 100644 --- a/src/m8/run.c +++ b/src/m8/run.c @@ -9,6 +9,8 @@ #include #include "../utils.h" +#include "../globals.h" +#include "../paleinfo.h" #include "../usb/shim.h" #include "../usb/pongo_helper.h" @@ -16,10 +18,6 @@ #include "dfu.h" #include "payload.h" -#include "../gen/payloads/checkra1n-kpf-pongo.h" -#include "../gen/payloads/ramdisk.h" -#include "../gen/payloads/binpack.h" - static void *exploit_thread(void *arg) { LOG("Waiting for DFU devices..."); @@ -142,18 +140,35 @@ static void *pongo_thread(void *arg) LOG_SUCCESS("Pongo device detected!"); + if (palerain_flags & palerain_option_pongo_exit) { + close_usb_handle(&handle); + atomic_store(&s->pongo_done, true); + atomic_store(&s->stage, STAGE_DONE); + break; + } + char paleinfo[64]; snprintf(paleinfo, sizeof(paleinfo), "palera1n_flags 0x%" PRIx64, palerain_flags); + char xargs_cmd[0x270]; + snprintf(xargs_cmd, sizeof(xargs_cmd), "xargs %s", boot_args); + if ((palerain_flags & palerain_option_setup_rootful)) { + strncat(xargs_cmd, " wdt=-1", 0x270 - strlen(xargs_cmd) - 1); + } + + LOG("Boot arguments: %s", xargs_cmd); + issue_pongo_command(&handle, "fuse lock"); issue_pongo_command(&handle, "sep auto"); - upload_buffer_to_pongo(&handle, payloads_checkra1n_kpf_pongo, payloads_checkra1n_kpf_pongo_len); + upload_buffer_to_pongo(&handle, g_payload_kpf.data, g_payload_kpf.data_len); issue_pongo_command(&handle, "modload"); issue_pongo_command(&handle, paleinfo); - upload_buffer_to_pongo(&handle, payloads_ramdisk_dmg, payloads_ramdisk_dmg_len); + upload_buffer_to_pongo(&handle, g_payload_ramdisk.data, g_payload_ramdisk.data_len); issue_pongo_command(&handle, "ramdisk"); - upload_buffer_to_pongo(&handle, payloads_binpack_dmg, payloads_binpack_dmg_len); + upload_buffer_to_pongo(&handle, g_payload_overlay.data, g_payload_overlay.data_len); issue_pongo_command(&handle, "overlay"); + if (strlen(boot_args) > 0) + issue_pongo_command(&handle, xargs_cmd); issue_pongo_command(&handle, "bootx"); atomic_store(&s->pongo_done, true); diff --git a/src/main.cpp b/src/main.cpp index 5de46ea..31e66be 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -12,6 +12,7 @@ #include "m8/run.h" #include "utils.h" +#include "globals.h" #include "paleinfo.h" #ifdef _WIN32 # include "usb/driver.h" @@ -42,22 +43,34 @@ void print_usage(char* argv) { "Usage: %s [OPTIONS]\n\n" " -h, --help Print usage information\n" " -v, --version Print version\n\n" - "Options:\n" - " --cli Use command line interface\n" + "Options:\n\n" + " --cli [f] Use command line interface\n" #ifdef WITH_GUI - " --gui Use graphical user interface\n" + " --gui [f] Use graphical user interface\n" #endif - " --force-revert Force environment reversion\n" - " -l, --rootless Enable rootless mode (standard)\n" - " -f, --rootful Enable rootful mode\n" - " -c, --setup-fakefs Setup fake filesystem\n" - " -B, --setup-partial-fakefs Setup partial fake filesystem\n" - " -s, --safe-mode Enable safe mode\n" - " -T, --telnetd Enable TELNET daemon on port 46 (insecure)\n" - " -V, --verbose-boot Enable verbose booting\n" + #ifdef WITH_TUI + " --tui [f] Use terminal user interface\n" + #endif + " --dark-blockchain [f] Enable dark blockchain\n" + " --force-revert [f] Force environment reversion\n" + " -l, --rootless [f] Enable rootless mode (standard)\n" + " -f, --rootful [f] Boots fakefs\n" + " -c, --setup-fakefs [f] Setup fake filesystem\n" + " -B, --setup-partial-fakefs [f] Setup partial fake filesystem\n" + " -s, --safe-mode [f] Enable safe mode\n" + " -T, --telnetd [f] Enable TELNET daemon on port 46 (insecure)\n" + " -V, --verbose-boot [f] Enable verbose booting\n" + " -p, --early-exit [f] Exit after uploading Pongo\n" + " -e, --extra-bootargs Set extra bootargs\n" + " -k, --override-pongo Override Pongo image\n" + " -K, --override-kpf Override kernel patchfinder\n" + " -o, --override-overlay Override overlay\n" + " -r, --override-ramdisk Override ramdisk\n" + " -n, --no-colors [f] Disable colors on the command line\n" + " -q, --quick [f] Enable Quick Mode\n" #ifdef _WIN32 - " --install-drivers Install libusbK drivers for PID\n" - " --remove-drivers Remove libusbK drivers for PID\n" + " --install-drivers Install libusbK drivers for PID\n" + " --remove-drivers Remove libusbK drivers for PID\n" #endif , argv ); @@ -72,9 +85,13 @@ void parse_arguments(int argc, char* argv[]) { {"version", no_argument, NULL, 'v'}, {"cli", no_argument, NULL, 1}, #ifdef WITH_GUI - {"gui", no_argument, NULL, 3}, + {"gui", no_argument, NULL, 2}, #endif - {"force-revert", no_argument, NULL, 0}, + #ifdef WITH_GUI + {"tui", no_argument, NULL, 3}, + #endif + {"dark-blockchain", no_argument, NULL, 4}, + {"force-revert", no_argument, NULL, 5}, {"rootless", no_argument, NULL, 'l'}, {"rootful", no_argument, NULL, 'f'}, {"setup-fakefs", no_argument, NULL, 'c'}, @@ -82,9 +99,17 @@ void parse_arguments(int argc, char* argv[]) { {"safe-mode", no_argument, NULL, 's'}, {"telnetd", no_argument, NULL, 'T'}, {"verbose-boot", no_argument, NULL, 'V'}, + {"early-exit", no_argument, NULL, 'p'}, + {"extra-bootargs", required_argument, NULL, 'e'}, + {"override-pongo", required_argument, NULL, 'k'}, + {"override-kpf", required_argument, NULL, 'K'}, + {"override-overlay", required_argument, NULL, 'o'}, + {"override-ramdisk", required_argument, NULL, 'r'}, + {"no-colors", no_argument, NULL, 'n'}, + {"quick", no_argument, NULL, 'q'}, #ifdef _WIN32 - {"install-drivers", required_argument, NULL, 2}, - {"remove-drivers", required_argument, NULL, 4}, + {"install-drivers", required_argument, NULL, 6}, + {"remove-drivers", required_argument, NULL, 7}, #endif {NULL, 0, NULL, 0} }; @@ -93,8 +118,13 @@ void parse_arguments(int argc, char* argv[]) { palerain_flags |= palerain_option_gui; # ifndef _WIN32 if (isatty(STDIN_FILENO) && getenv("LLVM_PROFILE_FILE") == nullptr) { + #ifdef WITH_TUI + palerain_flags &= ~palerain_option_gui; + palerain_flags |= palerain_option_tui; + #else palerain_flags &= ~palerain_option_gui; palerain_flags |= palerain_option_cli; + #endif } else { palerain_flags &= ~palerain_option_cli; palerain_flags |= palerain_option_gui; @@ -104,7 +134,7 @@ void parse_arguments(int argc, char* argv[]) { palerain_flags |= palerain_option_cli; #endif - while ((options = getopt_long(argc, argv, "hvlfcB:sTV", long_options, &option_index)) != -1) { + while ((options = getopt_long(argc, argv, "hvlfcB:sTVpe:k:K:o:r:nq", long_options, &option_index)) != -1) { switch (options) { case 'h': // --help print_usage(argv[0]); @@ -117,13 +147,23 @@ void parse_arguments(int argc, char* argv[]) { palerain_flags |= palerain_option_cli; break; #ifdef WITH_GUI - case 3: // --gui + case 2: // --gui palerain_flags &= ~palerain_option_cli; palerain_flags &= ~palerain_option_tui; palerain_flags |= palerain_option_gui; break; #endif - case 0: // --force-revert + #ifdef WITH_TUI + case 3: // --tui + palerain_flags &= ~palerain_option_cli; + palerain_flags &= ~palerain_option_gui; + palerain_flags |= palerain_option_tui; + break; + #endif + case 4: // --dark-blockchain + palerain_flags |= palerain_option_flower_chain; + break; + case 5: // --force-revert palerain_flags |= palerain_option_force_revert; break; case 'l': // --rootless @@ -149,8 +189,52 @@ void parse_arguments(int argc, char* argv[]) { case 'V': // --verbose-boot palerain_flags |= palerain_option_verbose_boot; break; + case 'p': // --early-exit + palerain_flags |= palerain_option_pongo_exit; + break; + case 'e': // --extra-bootargs + if (strlen(optarg) > (sizeof(boot_args) - 0x20)) { + LOG_ERROR("Boot arguments too long"); + exit(1); + } + snprintf(boot_args, sizeof(boot_args), "%s", optarg); + break; + case 'k': // --override-pongo + if (!override_payload_from_file(optarg, &g_payload_pongo)) { + LOG_ERROR("Failed to load pongo payload\n"); + exit(1); + } + LOG("Overriding pongo payload with %s", optarg); + break; + case 'K': // --override-kpf + if (!override_payload_from_file(optarg, &g_payload_kpf)) { + LOG_ERROR("Failed to load kpf payload\n"); + exit(1); + } + LOG("Overriding kpf payload with %s", optarg); + break; + case 'o': // --override-overlay + if (!override_payload_from_file(optarg, &g_payload_overlay)) { + LOG_ERROR("Failed to load overlay payload\n"); + exit(1); + } + LOG("Overriding overlay payload with %s", optarg); + break; + case 'r': // --override-ramdisk + if (!override_payload_from_file(optarg, &g_payload_ramdisk)) { + LOG_ERROR("Failed to load ramdisk payload\n"); + exit(1); + } + LOG("Overriding ramdisk payload with %s", optarg); + break; + case 'n': // --no-colors + palerain_flags |= palerain_option_no_colors; + break; + case 'q': // --quick + palerain_flags |= palerain_option_quick; + break; #ifdef _WIN32 - case 2: { // --install-drivers + case 6: { // --install-drivers unsigned short parsed_pid = (unsigned short)strtol(optarg, NULL, 16); if (parsed_pid == 0) { LOG_ERROR("Invalid PID value provided\n"); @@ -159,7 +243,7 @@ void parse_arguments(int argc, char* argv[]) { install_libusbk_target(0x05AC, parsed_pid); exit(0); } - case 4: { // --remove-drivers + case 7: { // --remove-drivers unsigned short parsed_pid = (unsigned short)strtol(optarg, NULL, 16); if (parsed_pid == 0) { LOG_ERROR("Invalid PID value provided\n"); diff --git a/src/paleinfo.h b/src/paleinfo.h index f84b713..47d35b9 100644 --- a/src/paleinfo.h +++ b/src/paleinfo.h @@ -48,6 +48,7 @@ typedef uint64_t palerain_option_t; #define palerain_option_jbinit_log_to_file (UINT64_C(1) << 30) /* deprecated (kept for compatibility) */ #define palerain_option_cli (UINT64_C(1) << 31) /* CLI mode */ #define palerain_option_telnetd (UINT64_C(1) << 32) /* Enable TELNET daemon */ +#define palerain_option_quick (UINT64_C(1) << 33) /* Quick mode */ #define palerain_option_flower_chain (UINT64_C(1) << 61) /* Flower chain */ #define palerain_option_test1 (UINT64_C(1) << 62) /* Developer test option 1 */ diff --git a/src/usb/driver.c b/src/usb/driver.c index 8fda6e0..4e6cb41 100644 --- a/src/usb/driver.c +++ b/src/usb/driver.c @@ -58,9 +58,9 @@ int install_libusbk_target(unsigned short vid, unsigned short pid) if (wdi_prepare_driver(d, driver_path, "libusbk_driver.inf", &prep) != WDI_SUCCESS || wdi_install_driver(d, driver_path, "libusbk_driver.inf", &inst) != WDI_SUCCESS) { - LOG_ERROR("Driver management pipeline failed for instance node."); + LOG_ERROR("Driver management pipeline failed for instance node"); } else { - LOG_SUCCESS("Driver successfully installed!"); + LOG_SUCCESS("Driver successfully installed"); } } @@ -128,7 +128,7 @@ int uninstall_libusbk_target(unsigned short vid, unsigned short pid) return 0; } - LOG_ERROR("No matching libusbK driver package found in system store."); + LOG_ERROR("No matching libusbK driver package found in system store"); return 2; } diff --git a/src/usb/pongo_helper.c b/src/usb/pongo_helper.c index 4a55972..502095e 100644 --- a/src/usb/pongo_helper.c +++ b/src/usb/pongo_helper.c @@ -9,14 +9,15 @@ #include "shim.h" #include "../utils.h" +#include "../globals.h" #include "../m8/dfu.h" -#include "../gen/payloads/Pongo.h" + #include "../gen/payloads/lz4dec.h" void compress_pongo(void *out, size_t *out_len) { - size_t len = payloads_Pongo_bin_len; + size_t len = g_payload_pongo.data_len; size_t out_len_ = *out_len; - *out_len = LZ4_compress_HC(payloads_Pongo_bin, out, len, out_len_, LZ4HC_CLEVEL_MAX); + *out_len = LZ4_compress_HC(g_payload_pongo.data, out, len, out_len_, LZ4HC_CLEVEL_MAX); } void checkm8_boot_pongo(usb_handle_t *handle) { @@ -26,10 +27,10 @@ void checkm8_boot_pongo(usb_handle_t *handle) { LOG_VERBOSE("Appending shellcode to the top of pongoOS (512 bytes)"); void *shellcode = malloc(512); memcpy(shellcode, payloads_lz4dec_bin, payloads_lz4dec_bin_len); - size_t out_len = payloads_Pongo_bin_len; + size_t out_len = g_payload_pongo.data_len; void *out = malloc(out_len); compress_pongo(out, &out_len); - LOG_VERBOSE("Compressed pongoOS from %u to %zu bytes", payloads_Pongo_bin_len, out_len); + LOG_VERBOSE("Compressed pongoOS from %u to %zu bytes", g_payload_pongo.data_len, out_len); void *tmp = malloc(out_len + 512); memcpy(tmp, shellcode, 512); memcpy(tmp + 512, out, out_len); @@ -124,7 +125,7 @@ int issue_pongo_command(const usb_handle_t *handle, const char *command) { bool upload_buffer_to_pongo(usb_handle_t *handle, const void *data, size_t length) { if (data == NULL || length == 0) { - LOG_ERROR("Invalid data buffer or length."); + LOG_ERROR("Invalid data buffer or length"); return false; } diff --git a/src/utils.c b/src/utils.c index 3c6e295..9cbbd02 100644 --- a/src/utils.c +++ b/src/utils.c @@ -1,15 +1,15 @@ #include "utils.h" -#ifdef _WIN32 -# include -#else -# include -#endif - #include #include #include #include +#ifdef _WIN32 +# include +#endif + +#include "globals.h" +#include "paleinfo.h" static const char* level_color(log_level_t level) { switch (level) { @@ -17,7 +17,7 @@ static const char* level_color(log_level_t level) { case LOG_SUCCESS: return GREEN_COLOR; case LOG_WARN: return YELLOW_COLOR; case LOG_ERROR: return RED_COLOR; - case LOG_VERBOSE: return GRAY_COLOR; + case LOG_VERBOSE: return RESET_COLOR; default: return RESET_COLOR; } } @@ -37,7 +37,7 @@ static const char* get_timestamp(void) { static char buffer[32]; time_t raw_time = time(NULL); struct tm *time_info = localtime(&raw_time); - + if (time_info) { // YYYY-MM-DD HH:MM:SS strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", time_info); @@ -54,9 +54,15 @@ void log_write(log_level_t level, const char *fmt, ...) { char tag_buf[32]; snprintf(tag_buf, sizeof(tag_buf), "<%s>", level_name(level)); - printf(" %s%-9s%s [%s%s%s] => ", - level_color(level), tag_buf, RESET_COLOR, - GRAY_COLOR, get_timestamp(), RESET_COLOR); + if (palerain_flags & palerain_option_no_colors) { + printf(" %s%-9s%s [%s%s%s] => ", + "", tag_buf, "", + "", get_timestamp(), ""); + } else { + printf(" %s%-9s%s [%s%s%s] => ", + level_color(level), tag_buf, RESET_COLOR, + GRAY_COLOR, get_timestamp(), RESET_COLOR); + } vprintf(fmt, args); printf("\n"); @@ -75,5 +81,3 @@ void sleep_ms(unsigned ms) { nanosleep(&ts, NULL); #endif } - -uint64_t palerain_flags = 0; \ No newline at end of file diff --git a/src/utils.h b/src/utils.h index 7845260..8e4f8f8 100644 --- a/src/utils.h +++ b/src/utils.h @@ -5,6 +5,7 @@ #include #include +#include #include #define RESET_COLOR "\033[0m" @@ -25,11 +26,11 @@ typedef enum { LOG_VERBOSE } log_level_t; -#define LOG(fmt, ...) log_write(LOG_INFO, fmt, ##__VA_ARGS__) -#define LOG_SUCCESS(fmt, ...) log_write(LOG_SUCCESS, fmt, ##__VA_ARGS__) -#define LOG_WARN(fmt, ...) log_write(LOG_WARN, fmt, ##__VA_ARGS__) -#define LOG_ERROR(fmt, ...) log_write(LOG_ERROR, fmt, ##__VA_ARGS__) -#define LOG_VERBOSE(fmt, ...) log_write(LOG_VERBOSE, fmt, ##__VA_ARGS__) +#define LOG(fmt, ...) log_write(LOG_INFO, fmt, ##__VA_ARGS__) +#define LOG_SUCCESS(fmt, ...) log_write(LOG_SUCCESS, fmt, ##__VA_ARGS__) +#define LOG_WARN(fmt, ...) log_write(LOG_WARN, fmt, ##__VA_ARGS__) +#define LOG_ERROR(fmt, ...) log_write(LOG_ERROR, fmt, ##__VA_ARGS__) +#define LOG_VERBOSE(fmt, ...) log_write(LOG_VERBOSE, fmt, ##__VA_ARGS__) #ifdef __cplusplus extern "C" { @@ -50,6 +51,4 @@ static inline const char* time_now() { return buf; } -extern uint64_t palerain_flags; - #endif // CONSTANTS_H diff --git a/src/wx/DevicePanel.hpp b/src/wx/DevicePanel.hpp index a43dfaa..bae4bd4 100644 --- a/src/wx/DevicePanel.hpp +++ b/src/wx/DevicePanel.hpp @@ -19,6 +19,10 @@ public: m_deviceState = state; } + virtual void OnShow(wxShowEvent& event) + { + event.Skip(); + } protected: MainFrame* GetMainFrame() const { @@ -29,7 +33,6 @@ protected: { return m_deviceState; } - private: MainFrame* m_frame; DeviceState m_deviceState; diff --git a/src/wx/DfuPanel.cpp b/src/wx/DfuPanel.cpp index 51dc5e4..5f0948b 100644 --- a/src/wx/DfuPanel.cpp +++ b/src/wx/DfuPanel.cpp @@ -4,9 +4,12 @@ #include "AppFrame.hpp" #include "DevicePanel.hpp" + #include "../state.hpp" #include "../sequence.hpp" #include "../utils.h" +#include "../globals.h" +#include "../paleinfo.h" #include @@ -31,6 +34,7 @@ DfuPanel::DfuPanel(MainFrame* frame, wxWindow* parent) : DevicePanel(frame, parent) { + Bind(wxEVT_SHOW, &DfuPanel::OnShow, this); auto* root = new wxBoxSizer(wxVERTICAL); m_headerText = new wxStaticText(this, wxID_ANY, "Time to put the device into DFU mode. Locate the buttons as marked below\non your device and check the instructions on the right."); @@ -141,6 +145,22 @@ void DfuPanel::SetDeviceState(const DeviceState& state) } } +void DfuPanel::OnShow(wxShowEvent& event) +{ + if (event.IsShown()) + { + if (palerain_flags & palerain_option_quick) { + m_isEnteringDfu = true; + m_backButton->Disable(); + m_startButton->Disable(); + + StartSequence(m_sequence); + } + } + + DevicePanel::OnShow(event); +} + void DfuPanel::LoadDevice(const std::string& productType) { const wxColour kActive = diff --git a/src/wx/DfuPanel.hpp b/src/wx/DfuPanel.hpp index 2aca382..af62642 100644 --- a/src/wx/DfuPanel.hpp +++ b/src/wx/DfuPanel.hpp @@ -14,6 +14,7 @@ class DfuPanel : public DevicePanel public: explicit DfuPanel(MainFrame* frame, wxWindow* parent); void SetDeviceState(const DeviceState& state) override; + void OnShow(wxShowEvent& event) override; void LoadDevice(const std::string& productType); void StartSequence(const DfuSequence& seq); void RunStep(); diff --git a/src/wx/MainPanel.cpp b/src/wx/MainPanel.cpp index a8f82df..7716ce1 100644 --- a/src/wx/MainPanel.cpp +++ b/src/wx/MainPanel.cpp @@ -10,8 +10,11 @@ #include "AppFrame.hpp" #include "DevicePanel.hpp" -#include "../state.hpp" +#include "../state.hpp" +#include "../globals.h" +#include "../utils.h" +#include "../paleinfo.h" #include "../gen/images/logo.h" const char* deviceTextString = "Connect your iPhone, iPod touch, iPad, or AppleTV to begin."; @@ -82,11 +85,21 @@ MainPanel::MainPanel(MainFrame* frame, wxWindow* parent) root->AddStretchSpacer(); - auto* btn = new wxButton(this, wxID_ANY, "Options"); + auto* quickMode = new wxCheckBox(this, wxID_ANY, "Quick Mode"); + auto* optionsButton = new wxButton(this, wxID_ANY, "Options"); m_startButton = new wxButton(this, wxID_ANY, "Start"); m_startButton->Disable(); - btn->Bind(wxEVT_BUTTON, [frame](wxCommandEvent&) + quickMode->SetValue(palerain_flags & palerain_option_quick); + quickMode->Bind(wxEVT_CHECKBOX, [&](wxCommandEvent& e) + { + if (e.IsChecked()) + palerain_flags |= palerain_option_quick; + else + palerain_flags &= ~palerain_option_quick; + }); + + optionsButton->Bind(wxEVT_BUTTON, [frame](wxCommandEvent&) { frame->ShowSettings(); }); @@ -105,7 +118,8 @@ MainPanel::MainPanel(MainFrame* frame, wxWindow* parent) auto* bottomRow = new wxBoxSizer(wxHORIZONTAL); bottomRow->AddStretchSpacer(); - bottomRow->Add(btn, 0, wxRIGHT | wxBOTTOM, 10); + bottomRow->Add(quickMode, 0, wxRIGHT | wxTOP, 1); + bottomRow->Add(optionsButton, 0, wxRIGHT | wxLEFT | wxBOTTOM, 10); bottomRow->Add(m_startButton, 0, wxRIGHT | wxLEFT | wxBOTTOM, 10); root->Add(bottomRow, 0, wxEXPAND); diff --git a/src/wx/RecoveryPanel.cpp b/src/wx/RecoveryPanel.cpp index 703eb4a..fc456b1 100644 --- a/src/wx/RecoveryPanel.cpp +++ b/src/wx/RecoveryPanel.cpp @@ -4,9 +4,15 @@ #include +#include + #include "AppFrame.hpp" #include "DevicePanel.hpp" + #include "../state.hpp" +#include "../utils.h" +#include "../globals.h" +#include "../paleinfo.h" #include #include @@ -15,6 +21,7 @@ RecoveryPanel::RecoveryPanel(MainFrame* frame, wxWindow* parent) : DevicePanel(frame, parent) { + Bind(wxEVT_SHOW, &RecoveryPanel::OnShow, this); auto* root = new wxBoxSizer(wxVERTICAL); root->Add(new wxStaticText(this, wxID_ANY, @@ -92,34 +99,52 @@ void RecoveryPanel::SetDeviceState(const DeviceState& state) } } +void RecoveryPanel::OnShow(wxShowEvent& event) +{ + if (event.IsShown()) + { + if (palerain_flags & palerain_option_quick) + { + m_statusText->SetLabel("Entering recovery mode..."); + m_backButton->Disable(); + m_nextButton->Disable(); + EnterRecoveryMode(); + } + } + + DevicePanel::OnShow(event); +} + void RecoveryPanel::EnterRecoveryMode() { - const auto& state = GetDeviceState(); + std::thread([this]() + { + const auto deviceState = GetDeviceState(); + if (!deviceState.connected) + return; - if (!state.connected) - return; + idevice_t device = nullptr; + lockdownd_client_t client = nullptr; - idevice_t device = nullptr; - lockdownd_client_t client = nullptr; + if (idevice_new(&device, deviceState.udid.c_str()) != IDEVICE_E_SUCCESS) + return; - if (idevice_new(&device, state.udid.c_str()) != IDEVICE_E_SUCCESS) - return; - - if (lockdownd_client_new_with_handshake( + if (lockdownd_client_new_with_handshake( device, &client, "palera1n") != LOCKDOWN_E_SUCCESS) - { + { + idevice_free(device); + return; + } + + m_isEnteringRecovery = true; + + lockdownd_enter_recovery(client); + + lockdownd_client_free(client); idevice_free(device); - return; - } - - m_isEnteringRecovery = true; - - lockdownd_enter_recovery(client); - - lockdownd_client_free(client); - idevice_free(device); + }).detach(); } void RecoveryPanel::SetStatusText(const wxString& text) diff --git a/src/wx/RecoveryPanel.hpp b/src/wx/RecoveryPanel.hpp index def9019..3f3c155 100644 --- a/src/wx/RecoveryPanel.hpp +++ b/src/wx/RecoveryPanel.hpp @@ -14,6 +14,7 @@ public: void SetDeviceState(const DeviceState& state) override; void SetStatusText(const wxString& text); void EnterRecoveryMode(); + void OnShow(wxShowEvent& event) override; private: wxButton* m_backButton = nullptr; wxButton* m_nextButton = nullptr; diff --git a/src/wx/SettingsPanel.cpp b/src/wx/SettingsPanel.cpp index 4728153..2c5d9ac 100644 --- a/src/wx/SettingsPanel.cpp +++ b/src/wx/SettingsPanel.cpp @@ -7,6 +7,7 @@ #include "AppFrame.hpp" #include "DevicePanel.hpp" #include "../utils.h" +#include "../globals.h" #include "../paleinfo.h" SettingsPanel::SettingsPanel(MainFrame* frame, wxWindow* parent) @@ -66,6 +67,18 @@ SettingsPanel::SettingsPanel(MainFrame* frame, wxWindow* parent) root->Add(new wxStaticText(this, wxID_ANY, "Boot Arguments:"), 0, wxALL, 10); auto* bootArgs = new wxTextCtrl(this, wxID_ANY, "", wxDefaultPosition, wxDefaultSize); + + bootArgs->SetValue(wxString(boot_args, wxConvUTF8)); + bootArgs->Bind(wxEVT_TEXT, [&](wxCommandEvent& e) + { + wxString value = e.GetString(); + if (value.length() > (sizeof(boot_args) - 0x20)) { + LOG_ERROR("Boot arguments too long"); + return; + } + snprintf(boot_args, sizeof(boot_args), "%s", value.ToStdString().c_str()); + }); + root->Add(bootArgs, 0, wxLEFT | wxRIGHT | wxEXPAND, 30); root->Add(option_revert, 0, wxLEFT | wxRIGHT | wxTOP, 10);