int main(int argc, char **argv) { // Recovery needs to install world-readable files, so clear umask // set by init umask(0); Log_Offset = 0; // Set up temporary log file (/tmp/recovery.log) freopen(TMP_LOG_FILE, "a", stdout); setbuf(stdout, NULL); freopen(TMP_LOG_FILE, "a", stderr); setbuf(stderr, NULL); signal(SIGPIPE, SIG_IGN); // Handle ADB sideload if (argc == 3 && strcmp(argv[1], "--adbd") == 0) { property_set("ctl.stop", "adbd"); adb_main(argv[2]); return 0; } #ifdef RECOVERY_SDCARD_ON_DATA datamedia = true; #endif char crash_prop_val[PROPERTY_VALUE_MAX]; int crash_counter; property_get("twrp.crash_counter", crash_prop_val, "-1"); crash_counter = atoi(crash_prop_val) + 1; snprintf(crash_prop_val, sizeof(crash_prop_val), "%d", crash_counter); property_set("twrp.crash_counter", crash_prop_val); property_set("ro.twrp.boot", "1"); property_set("ro.twrp.version", TW_VERSION_STR); time_t StartupTime = time(NULL); printf("Starting TWRP %s on %s (pid %d)\n", TW_VERSION_STR, ctime(&StartupTime), getpid()); // Load default values to set DataManager constants and handle ifdefs DataManager::SetDefaultValues(); printf("Starting the UI..."); gui_init(); printf("=> Linking mtab\n"); symlink("/proc/mounts", "/etc/mtab"); if (TWFunc::Path_Exists("/etc/twrp.fstab")) { if (TWFunc::Path_Exists("/etc/recovery.fstab")) { printf("Renaming regular /etc/recovery.fstab -> /etc/recovery.fstab.bak\n"); rename("/etc/recovery.fstab", "/etc/recovery.fstab.bak"); } printf("Moving /etc/twrp.fstab -> /etc/recovery.fstab\n"); rename("/etc/twrp.fstab", "/etc/recovery.fstab"); } printf("=> Processing recovery.fstab\n"); if (!PartitionManager.Process_Fstab("/etc/recovery.fstab", 1)) { LOGERR("Failing out of recovery due to problem with recovery.fstab.\n"); return -1; } PartitionManager.Output_Partition_Logging(); // Load up all the resources gui_loadResources(); #ifdef HAVE_SELINUX if (TWFunc::Path_Exists("/prebuilt_file_contexts")) { if (TWFunc::Path_Exists("/file_contexts")) { printf("Renaming regular /file_contexts -> /file_contexts.bak\n"); rename("/file_contexts", "/file_contexts.bak"); } printf("Moving /prebuilt_file_contexts -> /file_contexts\n"); rename("/prebuilt_file_contexts", "/file_contexts"); } struct selinux_opt selinux_options[] = { { SELABEL_OPT_PATH, "/file_contexts" } }; selinux_handle = selabel_open(SELABEL_CTX_FILE, selinux_options, 1); if (!selinux_handle) printf("No file contexts for SELinux\n"); else printf("SELinux contexts loaded from /file_contexts\n"); { // Check to ensure SELinux can be supported by the kernel char *contexts = NULL; if (PartitionManager.Mount_By_Path("/cache", true) && TWFunc::Path_Exists("/cache/recovery")) { lgetfilecon("/cache/recovery", &contexts); if (!contexts) { lsetfilecon("/cache/recovery", "test"); lgetfilecon("/cache/recovery", &contexts); } } else { LOGINFO("Could not check /cache/recovery SELinux contexts, using /sbin/teamwin instead which may be inaccurate.\n"); lgetfilecon("/sbin/teamwin", &contexts); } if (!contexts) { gui_print_color("warning", "Kernel does not have support for reading SELinux contexts.\n"); } else { free(contexts); gui_print("Full SELinux support is present.\n"); } } #else gui_print_color("warning", "No SELinux support (no libselinux).\n"); #endif PartitionManager.Mount_By_Path("/cache", true); string Zip_File, Reboot_Value; bool Cache_Wipe = false, Factory_Reset = false, Perform_Backup = false, Shutdown = false; { TWPartition* misc = PartitionManager.Find_Partition_By_Path("/misc"); if (misc != NULL) { if (misc->Current_File_System == "emmc") { set_device_type('e'); set_device_name(misc->Actual_Block_Device.c_str()); } else if (misc->Current_File_System == "mtd") { set_device_type('m'); set_device_name(misc->MTD_Name.c_str()); } else { LOGERR("Unknown file system for /misc\n"); } } get_args(&argc, &argv); int index, index2, len; char* argptr; char* ptr; printf("Startup Commands: "); for (index = 1; index < argc; index++) { argptr = argv[index]; printf(" '%s'", argv[index]); len = strlen(argv[index]); if (*argptr == '-') {argptr++; len--;} if (*argptr == '-') {argptr++; len--;} if (*argptr == 'u') { ptr = argptr; index2 = 0; while (*ptr != '=' && *ptr != '\n') ptr++; // skip the = before grabbing Zip_File while (*ptr == '=') ptr++; if (*ptr) { Zip_File = ptr; } else LOGERR("argument error specifying zip file\n"); } else if (*argptr == 'w') { if (len == 9) Factory_Reset = true; else if (len == 10) Cache_Wipe = true; } else if (*argptr == 'n') { Perform_Backup = true; } else if (*argptr == 'p') { Shutdown = true; } else if (*argptr == 's') { ptr = argptr; index2 = 0; while (*ptr != '=' && *ptr != '\n') ptr++; if (*ptr) { Reboot_Value = *ptr; } } } printf("\n"); } if(crash_counter == 0) { property_list(Print_Prop, NULL); printf("\n"); } else { printf("twrp.crash_counter=%d\n", crash_counter); } // Check for and run startup script if script exists TWFunc::check_and_run_script("/sbin/runatboot.sh", "boot"); TWFunc::check_and_run_script("/sbin/postrecoveryboot.sh", "boot"); #ifdef TW_INCLUDE_INJECTTWRP // Back up TWRP Ramdisk if needed: TWPartition* Boot = PartitionManager.Find_Partition_By_Path("/boot"); LOGINFO("Backing up TWRP ramdisk...\n"); if (Boot == NULL || Boot->Current_File_System != "emmc") TWFunc::Exec_Cmd("injecttwrp --backup /tmp/backup_recovery_ramdisk.img"); else { string injectcmd = "injecttwrp --backup /tmp/backup_recovery_ramdisk.img bd=" + Boot->Actual_Block_Device; TWFunc::Exec_Cmd(injectcmd); } LOGINFO("Backup of TWRP ramdisk done.\n"); #endif bool Keep_Going = true; if (Perform_Backup) { DataManager::SetValue(TW_BACKUP_NAME, "(Auto Generate)"); if (!OpenRecoveryScript::Insert_ORS_Command("backup BSDCAE\n")) Keep_Going = false; } if (Keep_Going && !Zip_File.empty()) { string ORSCommand = "install " + Zip_File; if (!OpenRecoveryScript::Insert_ORS_Command(ORSCommand)) Keep_Going = false; } if (Keep_Going) { if (Factory_Reset) { if (!OpenRecoveryScript::Insert_ORS_Command("wipe data\n")) Keep_Going = false; } else if (Cache_Wipe) { if (!OpenRecoveryScript::Insert_ORS_Command("wipe cache\n")) Keep_Going = false; } } TWFunc::Update_Log_File(); // Offer to decrypt if the device is encrypted if (DataManager::GetIntValue(TW_IS_ENCRYPTED) != 0) { LOGINFO("Is encrypted, do decrypt page first\n"); if (gui_startPage("decrypt", 1, 1) != 0) { LOGERR("Failed to start decrypt GUI page.\n"); } else { // Check for and load custom theme if present gui_loadCustomResources(); } } else if (datamedia) { if (tw_get_default_metadata(DataManager::GetSettingsStoragePath().c_str()) != 0) { LOGINFO("Failed to get default contexts and file mode for storage files.\n"); } else { LOGINFO("Got default contexts and file mode for storage files.\n"); } } // Read the settings file #ifdef TW_HAS_MTP // We unmount partitions sometimes during early boot which may override // the default of MTP being enabled by auto toggling MTP off. This // will force it back to enabled then get overridden by the settings // file, assuming that an entry for tw_mtp_enabled is set. DataManager::SetValue("tw_mtp_enabled", 1); #endif DataManager::ReadSettingsFile(); // Fixup the RTC clock on devices which require it if(crash_counter == 0) TWFunc::Fixup_Time_On_Boot(); // Run any outstanding OpenRecoveryScript if (DataManager::GetIntValue(TW_IS_ENCRYPTED) == 0 && (TWFunc::Path_Exists(SCRIPT_FILE_TMP) || TWFunc::Path_Exists(SCRIPT_FILE_CACHE))) { OpenRecoveryScript::Run_OpenRecoveryScript(); } #ifdef TW_HAS_MTP // Enable MTP? char mtp_crash_check[PROPERTY_VALUE_MAX]; property_get("mtp.crash_check", mtp_crash_check, "0"); if (strcmp(mtp_crash_check, "0") == 0) { property_set("mtp.crash_check", "1"); if (DataManager::GetIntValue("tw_mtp_enabled") == 1 && ((DataManager::GetIntValue(TW_IS_ENCRYPTED) != 0 && DataManager::GetIntValue(TW_IS_DECRYPTED) != 0) || DataManager::GetIntValue(TW_IS_ENCRYPTED) == 0)) { LOGINFO("Enabling MTP during startup\n"); if (!PartitionManager.Enable_MTP()) PartitionManager.Disable_MTP(); else gui_print("MTP Enabled\n"); } else { PartitionManager.Disable_MTP(); } property_set("mtp.crash_check", "0"); } else { gui_print_color("warning", "MTP Crashed, not starting MTP on boot.\n"); DataManager::SetValue("tw_mtp_enabled", 0); PartitionManager.Disable_MTP(); } #else PartitionManager.Disable_MTP(); #endif // Launch the main GUI gui_start(); // Disable flashing of stock recovery TWFunc::Disable_Stock_Recovery_Replace(); // Check for su to see if the device is rooted or not if (PartitionManager.Mount_By_Path("/system", false)) { if (TWFunc::Path_Exists("/supersu/su") && !TWFunc::Path_Exists("/system/bin/su") && !TWFunc::Path_Exists("/system/xbin/su") && !TWFunc::Path_Exists("/system/bin/.ext/.su")) { // Device doesn't have su installed DataManager::SetValue("tw_busy", 1); if (gui_startPage("installsu", 1, 1) != 0) { LOGERR("Failed to start SuperSU install page.\n"); } } sync(); PartitionManager.UnMount_By_Path("/system", false); } // Reboot TWFunc::Update_Intent_File(Reboot_Value); TWFunc::Update_Log_File(); gui_print("Rebooting...\n"); string Reboot_Arg; DataManager::GetValue("tw_reboot_arg", Reboot_Arg); if (Reboot_Arg == "recovery") TWFunc::tw_reboot(rb_recovery); else if (Reboot_Arg == "poweroff") TWFunc::tw_reboot(rb_poweroff); else if (Reboot_Arg == "bootloader") TWFunc::tw_reboot(rb_bootloader); else if (Reboot_Arg == "download") TWFunc::tw_reboot(rb_download); else TWFunc::tw_reboot(rb_system); return 0; }
int main(int argc, char *argv[]) { enum { OPT_NO_LOG_FILE = 1000, }; static struct option long_options[] = { { "no-log-file", no_argument, 0, OPT_NO_LOG_FILE }, { "help", no_argument, 0, 'h' }, { 0, 0, 0, 0 } }; int opt; int long_index = 0; bool no_log_file = false; while ((opt = getopt_long(argc, argv, "h", long_options, &long_index)) != -1) { switch (opt) { case OPT_NO_LOG_FILE: no_log_file = true; break; case 'h': usage(stdout); return EXIT_SUCCESS; default: usage(stderr); return EXIT_FAILURE; } } // There should be one other argument if (argc - optind != 1) { usage(stderr); return EXIT_FAILURE; } umask(0); if (!mb::util::mkdir_recursive(MBBOOTUI_BASE_PATH, 0755)) { LOGE("%s: Failed to create directory: %s", MBBOOTUI_BASE_PATH, strerror(errno)); return EXIT_FAILURE; } // Rotate log if it is too large struct stat sb; if (stat(MBBOOTUI_LOG_PATH, &sb) == 0 && sb.st_size > MAX_LOG_SIZE) { rename(MBBOOTUI_LOG_PATH, MBBOOTUI_LOG_PATH ".prev"); } if (!no_log_file && !redirect_output_to_file(MBBOOTUI_LOG_PATH, 0600)) { return EXIT_FAILURE; } signal(SIGPIPE, SIG_IGN); // Set paths tw_resource_path = MBBOOTUI_THEME_PATH; tw_settings_path = MBBOOTUI_SETTINGS_PATH; tw_screenshots_path = MBBOOTUI_SCREENSHOTS_PATH; // Disallow custom themes, which could manipulate variables in such as way // as to execute malicious code tw_theme_zip_path = ""; if (!detect_device()) { return EXIT_FAILURE; } // Check if device supports the boot UI if (!device->twOptions()->supported) { LOGW("Boot UI is not supported for the device"); return EXIT_FAILURE; } // Load device configuration options load_device_config(); load_other_config(); log_startup(); if (!extract_theme(argv[optind], MBBOOTUI_THEME_PATH, device->twOptions()->theme)) { LOGE("Failed to extract theme"); return EXIT_FAILURE; } // Connect to daemon if (!mbtool_connection.connect()) { LOGE("Failed to connect to mbtool"); return EXIT_FAILURE; } mbtool_interface = mbtool_connection.interface(); LOGV("Loading default values..."); DataManager::SetDefaultValues(); // Set daemon version std::string mbtool_version; mbtool_interface->version(&mbtool_version); DataManager::SetValue(TW_MBTOOL_VERSION, mbtool_version); LOGV("Loading graphics system..."); if (gui_init() < 0) { LOGE("Failed to load graphics system"); return EXIT_FAILURE; } LOGV("Loading resources..."); gui_loadResources(); LOGV("Checking for encryption..."); char crypto_state[PROP_VALUE_MAX]; mb::util::property_get(PROP_CRYPTO_STATE, crypto_state, CRYPTO_STATE_DECRYPTED); if (strcmp(crypto_state, CRYPTO_STATE_ENCRYPTED) == 0) { LOGV("Data appears to be encrypted"); int is_encrypted = 1; // Ask mbtool for password type std::string pw_type; if (!mbtool_interface->crypto_get_pw_type(&pw_type)) { LOGE("Failed to ask mbtool for the crypto password type"); return EXIT_FAILURE; } // If password type is unknown, assume "password" if (pw_type.empty()) { LOGW("Crypto password type is unknown. Assuming 'password'"); pw_type = "password"; } // Try default password if (pw_type == "default") { bool ret; if (!mbtool_interface->crypto_decrypt("default_password", &ret)) { LOGE("Failed to ask mbtool to decrypt userdata"); return EXIT_FAILURE; } if (ret) { LOGV("Successfully decrypted device with default password"); is_encrypted = 0; } else { LOGW("Failed to decrypt device with default password despite " "password type being 'default'"); pw_type = "password"; } } DataManager::SetValue(TW_IS_ENCRYPTED, is_encrypted); DataManager::SetValue(TW_CRYPTO_PWTYPE, pw_type); DataManager::SetValue(TW_CRYPTO_PASSWORD, ""); DataManager::SetValue("tw_crypto_display", ""); if (is_encrypted) { LOGV("Showing decrypt page first due to encrypted device"); gui_startPage("decrypt", 1, 1); } if (DataManager::GetIntValue(TW_IS_ENCRYPTED) != 0) { LOGE("Decrypt page exited, but device is still encrypted"); mb::util::property_set(PROP_CRYPTO_STATE, CRYPTO_STATE_ERROR); return EXIT_FAILURE; } else { LOGV("Decrypt page exited and device was successfully decrypted"); mb::util::property_set(PROP_CRYPTO_STATE, CRYPTO_STATE_DECRYPTED); } } // Set ROM ID. This must happen after decryption or else the current ROM // will not be detected if it is a data-slot. mbtool's ROM detection code // doesn't fully trust the "ro.multiboot.romid" property and will do some // additional checks to ensure that the value is correct. std::string rom_id; mbtool_interface->get_booted_rom_id(&rom_id); if (rom_id.empty()) { LOGW("Could not determine ROM ID"); } DataManager::SetValue(TW_ROM_ID, rom_id); LOGV("Loading user settings..."); DataManager::ReadSettingsFile(); LOGV("Loading language..."); PageManager::LoadLanguage(DataManager::GetStrValue(TW_LANGUAGE)); GUIConsole::Translate_Now(); LOGV("Fixing time..."); TWFunc::Fixup_Time_On_Boot(); LOGV("Loading main UI..."); //gui_start(); gui_startPage("autoboot", 1, 0); // Exit action std::string exit_action; DataManager::GetValue(TW_EXIT_ACTION, exit_action); std::vector<std::string> args = mb::util::split(exit_action, ","); // Save settings DataManager::Flush(); if (args.size() > 0) { if (args[0] == "reboot") { std::string reboot_arg; if (args.size() > 1) { reboot_arg = args[1]; } bool result; mbtool_interface->reboot(reboot_arg, &result); wait_forever(); } else if (args[0] == "shutdown") { bool result; mbtool_interface->shutdown(&result); wait_forever(); } } return EXIT_SUCCESS; }
int main(int argc, char **argv) { // Recovery needs to install world-readable files, so clear umask // set by init umask(0); time_t start = time(NULL); // If these fail, there's not really anywhere to complain... freopen(TEMPORARY_LOG_FILE, "a", stdout); setbuf(stdout, NULL); freopen(TEMPORARY_LOG_FILE, "a", stderr); setbuf(stderr, NULL); // If this binary is started with the single argument "--adbd", // instead of being the normal recovery binary, it turns into kind // of a stripped-down version of adbd that only supports the // 'sideload' command. Note this must be a real argument, not // anything in the command file or bootloader control block; the // only way recovery should be run with this argument is when it // starts a copy of itself from the apply_from_adb() function. if (argc == 3 && strcmp(argv[1], "--adbd") == 0) { adb_main(argv[2]); return 0; } printf("Starting TWRP %s on %s", TW_VERSION_STR, ctime(&start)); Device* device = make_device(); ui = device->GetUI(); //ui->Init(); //ui->SetBackground(RecoveryUI::NONE); //load_volume_table(); // Load default values to set DataManager constants and handle ifdefs DataManager_LoadDefaults(); printf("Starting the UI..."); gui_init(); printf("=> Linking mtab\n"); symlink("/proc/mounts", "/etc/mtab"); printf("=> Processing recovery.fstab\n"); if (!PartitionManager.Process_Fstab("/etc/recovery.fstab", 1)) { LOGE("Failing out of recovery due to problem with recovery.fstab.\n"); //return -1; } PartitionManager.Output_Partition_Logging(); // Load up all the resources gui_loadResources(); PartitionManager.Mount_By_Path("/cache", true); get_args(&argc, &argv); int previous_runs = 0; const char *send_intent = NULL; const char *update_package = NULL; int wipe_data = 0, wipe_cache = 0; bool just_exit = false; bool perform_backup = false; int arg; while ((arg = getopt_long(argc, argv, "", OPTIONS, NULL)) != -1) { switch (arg) { case 'p': previous_runs = atoi(optarg); break; case 's': send_intent = optarg; break; case 'u': update_package = optarg; break; case 'w': wipe_data = wipe_cache = 1; break; case 'c': wipe_cache = 1; break; case 't': ui->ShowText(true); break; case 'x': just_exit = true; break; case 'n': perform_backup = true; LOGI("nandroid\n"); break; case '?': LOGE("Invalid command argument\n"); continue; } } #ifdef HAVE_SELINUX struct selinux_opt seopts[] = { { SELABEL_OPT_PATH, "/file_contexts" } }; sehandle = selabel_open(SELABEL_CTX_FILE, seopts, 1); if (!sehandle) { fprintf(stderr, "Warning: No file_contexts\n"); ui->Print("Warning: No file_contexts\n"); } #endif //device->StartRecovery(); printf("Command:"); for (arg = 0; arg < argc; arg++) { printf(" \"%s\"", argv[arg]); } printf("\n"); if (update_package) { // For backwards compatibility on the cache partition only, if // we're given an old 'root' path "CACHE:foo", change it to // "/cache/foo". if (strncmp(update_package, "CACHE:", 6) == 0) { int len = strlen(update_package) + 10; char* modified_path = (char*)malloc(len); strlcpy(modified_path, "/cache/", len); strlcat(modified_path, update_package+6, len); printf("(replacing path \"%s\" with \"%s\")\n", update_package, modified_path); update_package = modified_path; } } printf("\n"); property_list(print_property, NULL); printf("\n"); // Check for and run startup script if script exists TWFunc::check_and_run_script("/sbin/runatboot.sh", "boot"); TWFunc::check_and_run_script("/sbin/postrecoveryboot.sh", "boot"); #ifdef TW_INCLUDE_INJECTTWRP // Back up TWRP Ramdisk if needed: TWPartition* Boot = PartitionManager.Find_Partition_By_Path("/boot"); string result; LOGI("Backing up TWRP ramdisk...\n"); if (Boot == NULL || Boot->Current_File_System != "emmc") TWFunc::Exec_Cmd("injecttwrp --backup /tmp/backup_recovery_ramdisk.img", result); else { string injectcmd = "injecttwrp --backup /tmp/backup_recovery_ramdisk.img bd=" + Boot->Actual_Block_Device; TWFunc::Exec_Cmd(injectcmd, result); } LOGI("Backup of TWRP ramdisk done.\n"); #endif int status = INSTALL_SUCCESS; string ORSCommand; if (perform_backup) { char empt[50]; gui_console_only(); strcpy(empt, "(Current Date)"); DataManager_SetStrValue(TW_BACKUP_NAME, empt); if (!OpenRecoveryScript::Insert_ORS_Command("backup BSDCAE\n")) status = INSTALL_ERROR; } if (status == INSTALL_SUCCESS) { // Prevent other actions if backup failed if (update_package != NULL) { ORSCommand = "install "; ORSCommand += update_package; ORSCommand += "\n"; if (OpenRecoveryScript::Insert_ORS_Command(ORSCommand)) status = INSTALL_SUCCESS; else status = INSTALL_ERROR; /* status = install_package(update_package, &wipe_cache, TEMPORARY_INSTALL_FILE); if (status == INSTALL_SUCCESS && wipe_cache) { if (erase_volume("/cache")) { LOGE("Cache wipe (requested by package) failed."); } } if (status != INSTALL_SUCCESS) ui->Print("Installation aborted.\n"); */ } else if (wipe_data) { if (!OpenRecoveryScript::Insert_ORS_Command("wipe data\n")) status = INSTALL_ERROR; /* if (device->WipeData()) status = INSTALL_ERROR; if (erase_volume("/data")) status = INSTALL_ERROR; if (wipe_cache && erase_volume("/cache")) status = INSTALL_ERROR; */ if (status != INSTALL_SUCCESS) ui->Print("Data wipe failed.\n"); } else if (wipe_cache) { if (!OpenRecoveryScript::Insert_ORS_Command("wipe cache\n")) status = INSTALL_ERROR; if (status != INSTALL_SUCCESS) ui->Print("Cache wipe failed.\n"); } else if (!just_exit) { status = INSTALL_ERROR; // No command specified } } finish_recovery(NULL); // Offer to decrypt if the device is encrypted if (DataManager_GetIntValue(TW_IS_ENCRYPTED) != 0) { LOGI("Is encrypted, do decrypt page first\n"); if (gui_startPage("decrypt") != 0) { LOGE("Failed to start decrypt GUI page.\n"); } } // Read the settings file DataManager_ReadSettingsFile(); // Run any outstanding OpenRecoveryScript if (DataManager_GetIntValue(TW_IS_ENCRYPTED) == 0 && (TWFunc::Path_Exists(SCRIPT_FILE_TMP) || TWFunc::Path_Exists(SCRIPT_FILE_CACHE))) { OpenRecoveryScript::Run_OpenRecoveryScript(); } // Launch the main GUI gui_start(); // Check for su to see if the device is rooted or not if (PartitionManager.Mount_By_Path("/system", false)) { // Disable flashing of stock recovery if (TWFunc::Path_Exists("/system/recovery-from-boot.p")) { rename("/system/recovery-from-boot.p", "/system/recovery-from-boot.bak"); ui_print("Renamed stock recovery file in /system to prevent\nthe stock ROM from replacing TWRP.\n"); } if (TWFunc::Path_Exists("/supersu/su") && !TWFunc::Path_Exists("/system/bin/su") && !TWFunc::Path_Exists("/system/xbin/su") && !TWFunc::Path_Exists("/system/bin/.ext/.su")) { // Device doesn't have su installed DataManager_SetIntValue("tw_busy", 1); if (gui_startPage("installsu") != 0) { LOGE("Failed to start decrypt GUI page.\n"); } } else if (TWFunc::Check_su_Perms() > 0) { // su perms are set incorrectly DataManager_SetIntValue("tw_busy", 1); if (gui_startPage("fixsu") != 0) { LOGE("Failed to start decrypt GUI page.\n"); } } sync(); PartitionManager.UnMount_By_Path("/system", false); } // Otherwise, get ready to boot the main system... finish_recovery(send_intent); ui->Print("Rebooting...\n"); char backup_arg_char[50]; strcpy(backup_arg_char, DataManager_GetStrValue("tw_reboot_arg")); string backup_arg = backup_arg_char; if (backup_arg == "recovery") TWFunc::tw_reboot(rb_recovery); else if (backup_arg == "poweroff") TWFunc::tw_reboot(rb_poweroff); else if (backup_arg == "bootloader") TWFunc::tw_reboot(rb_bootloader); else if (backup_arg == "download") TWFunc::tw_reboot(rb_download); else TWFunc::tw_reboot(rb_system); #ifdef ANDROID_RB_RESTART android_reboot(ANDROID_RB_RESTART, 0, 0); #else reboot(RB_AUTOBOOT); #endif return EXIT_SUCCESS; }
int main(int argc, char *argv[]) { enum { OPT_NO_LOG_FILE = 1000, }; static struct option long_options[] = { { "no-log-file", no_argument, 0, OPT_NO_LOG_FILE }, { "help", no_argument, 0, 'h' }, { 0, 0, 0, 0 } }; int opt; int long_index = 0; bool no_log_file = false; while ((opt = getopt_long(argc, argv, "h", long_options, &long_index)) != -1) { switch (opt) { case OPT_NO_LOG_FILE: no_log_file = true; break; case 'h': usage(stdout); return EXIT_SUCCESS; default: usage(stderr); return EXIT_FAILURE; } } // There should be one other argument if (argc - optind != 1) { usage(stderr); return EXIT_FAILURE; } umask(0); if (!mb::util::mkdir_recursive(MBBOOTUI_BASE_PATH, 0755)) { LOGE("%s: Failed to create directory: %s", MBBOOTUI_BASE_PATH, strerror(errno)); return EXIT_FAILURE; } if (!no_log_file && !redirect_output_to_file(MBBOOTUI_LOG_PATH, 0600)) { return EXIT_FAILURE; } signal(SIGPIPE, SIG_IGN); // Set paths tw_resource_path = MBBOOTUI_THEME_PATH; tw_settings_path = MBBOOTUI_SETTINGS_PATH; tw_screenshots_path = MBBOOTUI_SCREENSHOTS_PATH; // Disallow custom themes, which could manipulate variables in such as way // as to execute malicious code tw_theme_zip_path = ""; if (!detect_device()) { return EXIT_FAILURE; } // Check if device supports the boot UI if (!device->twOptions()->supported) { LOGW("Boot UI is not supported for the device"); return EXIT_FAILURE; } // Load device configuration options load_device_config(); log_startup(); if (!extract_theme(argv[optind], MBBOOTUI_THEME_PATH, device->twOptions()->theme)) { LOGE("Failed to extract theme"); return EXIT_FAILURE; } // Connect to daemon if (!mbtool_connection.connect()) { LOGE("Failed to connect to mbtool"); return EXIT_FAILURE; } mbtool_interface = mbtool_connection.interface(); LOGV("Loading default values..."); DataManager::SetDefaultValues(); // Set daemon version std::string mbtool_version; mbtool_interface->version(&mbtool_version); DataManager::SetValue(TW_MBTOOL_VERSION, mbtool_version); // Set ROM ID std::string rom_id; mbtool_interface->get_booted_rom_id(&rom_id); DataManager::SetValue(TW_ROM_ID, rom_id); LOGV("Loading graphics system..."); if (gui_init() < 0) { LOGE("Failed to load graphics system"); return EXIT_FAILURE; } LOGV("Loading resources..."); gui_loadResources(); LOGV("Loading user settings..."); DataManager::ReadSettingsFile(); LOGV("Loading language..."); PageManager::LoadLanguage(DataManager::GetStrValue(TW_LANGUAGE)); GUIConsole::Translate_Now(); LOGV("Fixing time..."); TWFunc::Fixup_Time_On_Boot(); LOGV("Loading main UI..."); //gui_start(); gui_startPage("autoboot", 1, 0); // Exit action std::string exit_action; DataManager::GetValue(TW_EXIT_ACTION, exit_action); std::vector<std::string> args = mb::util::split(exit_action, ","); // Save settings DataManager::Flush(); if (args.size() > 0) { if (args[0] == "reboot") { std::string reboot_arg; if (args.size() > 1) { reboot_arg = args[1]; } bool result; mbtool_interface->reboot(reboot_arg, &result); wait_forever(); } else if (args[0] == "shutdown") { bool result; mbtool_interface->shutdown(&result); wait_forever(); } } return EXIT_SUCCESS; }