/* | |
Copyright 2013 bigbiff/Dees_Troy TeamWin | |
This file is part of TWRP/TeamWin Recovery Project. | |
TWRP is free software: you can redistribute it and/or modify | |
it under the terms of the GNU General Public License as published by | |
the Free Software Foundation, either version 3 of the License, or | |
(at your option) any later version. | |
TWRP 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 General Public License for more details. | |
You should have received a copy of the GNU General Public License | |
along with TWRP. If not, see <http://www.gnu.org/licenses/>. | |
*/ | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <sys/stat.h> | |
#include <sys/types.h> | |
#include <time.h> | |
#include <unistd.h> | |
#include "cutils/properties.h" | |
extern "C" { | |
#include "minadbd/adb.h" | |
} | |
#ifdef ANDROID_RB_RESTART | |
#include "cutils/android_reboot.h" | |
#else | |
#include <sys/reboot.h> | |
#endif | |
extern "C" { | |
#include "gui/gui.h" | |
} | |
#include "twcommon.h" | |
#include "twrp-functions.hpp" | |
#include "data.hpp" | |
#include "partitions.hpp" | |
#include "openrecoveryscript.hpp" | |
#include "variables.h" | |
TWPartitionManager PartitionManager; | |
int Log_Offset; | |
static void Print_Prop(const char *key, const char *name, void *cookie) { | |
printf("%s=%s\n", key, name); | |
} | |
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); | |
// Handle ADB sideload | |
if (argc == 3 && strcmp(argv[1], "--adbd") == 0) { | |
adb_main(argv[2]); | |
return 0; | |
} | |
time_t StartupTime = time(NULL); | |
printf("Starting TWRP %s on %s", TW_VERSION_STR, ctime(&StartupTime)); | |
// 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"); | |
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(); | |
PartitionManager.Mount_By_Path("/cache", true); | |
string Zip_File, Reboot_Value; | |
bool Cache_Wipe = false, Factory_Reset = false, Perform_Backup = false; | |
int index, index2; | |
char* ptr; | |
printf("Startup Commands: "); | |
for (index = 1; index < argc; index++) { | |
printf(" '%s'", argv[index]); | |
if (*argv[index] == 'u') { | |
ptr = argv[index]; | |
index2 = 0; | |
while (*ptr != '=' && *ptr != '\n') | |
ptr++; | |
if (*ptr) { | |
Zip_File = ptr; | |
} else | |
LOGERR("argument error specifying zip file\n"); | |
} else if (*argv[index] == 'c') { | |
Cache_Wipe = true; | |
} else if (*argv[index] == 'w') { | |
Factory_Reset = true; | |
} else if (*argv[index] == 'n') { | |
Perform_Backup = true; | |
} else if (*argv[index] == 's') { | |
ptr = argv[index]; | |
index2 = 0; | |
while (*ptr != '=' && *ptr != '\n') | |
ptr++; | |
if (*ptr) { | |
Reboot_Value = *ptr; | |
} | |
} | |
} | |
char twrp_booted[PROPERTY_VALUE_MAX]; | |
property_get("ro.twrp.boot", twrp_booted, "0"); | |
if (strcmp(twrp_booted, "0") != 0) { | |
property_list(Print_Prop, NULL); | |
printf("\n"); | |
property_set("ro.twrp.boot", "1"); | |
} | |
// 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; | |
LOGINFO("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); | |
} | |
LOGINFO("Backup of TWRP ramdisk done.\n"); | |
#endif | |
bool Keep_Going = true; | |
if (Perform_Backup) { | |
DataManager::SetValue(TW_BACKUP_NAME, "(Current Date)"); | |
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") != 0) { | |
LOGERR("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"); | |
gui_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::SetValue("tw_busy", 1); | |
if (gui_startPage("installsu") != 0) { | |
LOGERR("Failed to start decrypt GUI page.\n"); | |
} | |
} else if (TWFunc::Check_su_Perms() > 0) { | |
// su perms are set incorrectly | |
DataManager::SetValue("tw_busy", 1); | |
if (gui_startPage("fixsu") != 0) { | |
LOGERR("Failed to start decrypt GUI 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); | |
#ifdef ANDROID_RB_RESTART | |
android_reboot(ANDROID_RB_RESTART, 0, 0); | |
#else | |
reboot(RB_AUTOBOOT); | |
#endif | |
return 0; | |
} |