summaryrefslogtreecommitdiffstats
path: root/recovery.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'recovery.cpp')
-rw-r--r--recovery.cpp271
1 files changed, 103 insertions, 168 deletions
diff --git a/recovery.cpp b/recovery.cpp
index c6e12702d..1d22b248a 100644
--- a/recovery.cpp
+++ b/recovery.cpp
@@ -25,6 +25,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/klog.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
@@ -33,11 +34,7 @@
#include "bootloader.h"
#include "common.h"
#include "cutils/properties.h"
-#ifdef ANDROID_RB_RESTART
#include "cutils/android_reboot.h"
-#else
-#include <sys/reboot.h>
-#endif
#include "install.h"
#include "minui/minui.h"
#include "minzip/DirUtil.h"
@@ -52,20 +49,8 @@ extern "C" {
#include "fuse_sdcard_provider.h"
}
-extern "C" {
-#include "data.h"
-#include "gui/gui.h"
-}
-#include "partitions.hpp"
-#include "variables.h"
-#include "openrecoveryscript.hpp"
-#include "twrp-functions.hpp"
-
-TWPartitionManager PartitionManager;
-
struct selabel_handle *sehandle;
-
static const struct option OPTIONS[] = {
{ "send_intent", required_argument, NULL, 's' },
{ "update_package", required_argument, NULL, 'u' },
@@ -92,9 +77,14 @@ static const char *CACHE_ROOT = "/cache";
static const char *SDCARD_ROOT = "/sdcard";
static const char *TEMPORARY_LOG_FILE = "/tmp/recovery.log";
static const char *TEMPORARY_INSTALL_FILE = "/tmp/last_install";
+static const char *LAST_KMSG_FILE = "/cache/recovery/last_kmsg";
+#define KLOG_DEFAULT_LEN (64 * 1024)
#define KEEP_LOG_COUNT 10
+// Number of lines per page when displaying a file on screen
+#define LINES_PER_PAGE 30
+
RecoveryUI* ui = NULL;
char* locale = NULL;
char recovery_version[PROPERTY_VALUE_MAX+1];
@@ -275,8 +265,46 @@ set_sdcard_update_bootloader_message() {
set_bootloader_message(&boot);
}
+// read from kernel log into buffer and write out to file
+static void
+save_kernel_log(const char *destination) {
+ int n;
+ char *buffer;
+ int klog_buf_len;
+ FILE *log;
+
+ klog_buf_len = klogctl(KLOG_SIZE_BUFFER, 0, 0);
+ if (klog_buf_len <= 0) {
+ LOGE("Error getting klog size (%s), using default\n", strerror(errno));
+ klog_buf_len = KLOG_DEFAULT_LEN;
+ }
+
+ buffer = (char *)malloc(klog_buf_len);
+ if (!buffer) {
+ LOGE("Can't alloc %d bytes for klog buffer\n", klog_buf_len);
+ return;
+ }
+
+ n = klogctl(KLOG_READ_ALL, buffer, klog_buf_len);
+ if (n < 0) {
+ LOGE("Error in reading klog (%s)\n", strerror(errno));
+ free(buffer);
+ return;
+ }
+
+ log = fopen_path(destination, "w");
+ if (log == NULL) {
+ LOGE("Can't open %s\n", destination);
+ free(buffer);
+ return;
+ }
+ fwrite(buffer, n, 1, log);
+ check_and_fclose(log, destination);
+ free(buffer);
+}
+
// How much of the temp log we have copied to the copy in cache.
-//static long tmplog_offset = 0;
+static long tmplog_offset = 0;
static void
copy_log_file(const char* source, const char* destination, int append) {
@@ -322,8 +350,11 @@ copy_logs() {
copy_log_file(TEMPORARY_LOG_FILE, LOG_FILE, true);
copy_log_file(TEMPORARY_LOG_FILE, LAST_LOG_FILE, false);
copy_log_file(TEMPORARY_INSTALL_FILE, LAST_INSTALL_FILE, false);
+ save_kernel_log(LAST_KMSG_FILE);
chmod(LOG_FILE, 0600);
chown(LOG_FILE, 1000, 1000); // system user
+ chmod(LAST_KMSG_FILE, 0600);
+ chown(LAST_KMSG_FILE, 1000, 1000); // system user
chmod(LAST_LOG_FILE, 0640);
chmod(LAST_INSTALL_FILE, 0644);
sync();
@@ -697,29 +728,71 @@ static void file_to_ui(const char* fn) {
}
char line[1024];
int ct = 0;
+ int key = 0;
redirect_stdio("/dev/null");
while(fgets(line, sizeof(line), fp) != NULL) {
ui->Print("%s", line);
ct++;
- if (ct % 30 == 0) {
+ if (ct % LINES_PER_PAGE == 0) {
// give the user time to glance at the entries
- ui->WaitKey();
+ key = ui->WaitKey();
+
+ if (key == KEY_POWER) {
+ break;
+ }
+
+ if (key == KEY_VOLUMEUP) {
+ // Go back by seeking to the beginning and dumping ct - n
+ // lines. It's ugly, but this way we don't need to store
+ // the previous offsets. The files we're dumping here aren't
+ // expected to be very large.
+ int i;
+
+ ct -= 2 * LINES_PER_PAGE;
+ if (ct < 0) {
+ ct = 0;
+ }
+ fseek(fp, 0, SEEK_SET);
+ for (i = 0; i < ct; i++) {
+ fgets(line, sizeof(line), fp);
+ }
+ ui->Print("^^^^^^^^^^\n");
+ }
}
}
+
+ // If the user didn't abort, then give the user time to glance at
+ // the end of the log, sorry, no rewind here
+ if (key != KEY_POWER) {
+ ui->Print("\n--END-- (press any key)\n");
+ ui->WaitKey();
+ }
+
redirect_stdio(TEMPORARY_LOG_FILE);
fclose(fp);
}
static void choose_recovery_file(Device* device) {
- int i;
+ unsigned int i;
+ unsigned int n;
static const char** title_headers = NULL;
char *filename;
const char* headers[] = { "Select file to view",
"",
NULL };
- char* entries[KEEP_LOG_COUNT + 2];
+ // "Go back" + LAST_KMSG_FILE + KEEP_LOG_COUNT + terminating NULL entry
+ char* entries[KEEP_LOG_COUNT + 3];
memset(entries, 0, sizeof(entries));
+ n = 0;
+ entries[n++] = strdup("Go back");
+
+ // Add kernel kmsg file if available
+ if ((ensure_path_mounted(LAST_KMSG_FILE) == 0) && (access(LAST_KMSG_FILE, R_OK) == 0)) {
+ entries[n++] = strdup(LAST_KMSG_FILE);
+ }
+
+ // Add LAST_LOG_FILE + LAST_LOG_FILE.x
for (i = 0; i < KEEP_LOG_COUNT; i++) {
char *filename;
if (asprintf(&filename, (i==0) ? LAST_LOG_FILE : (LAST_LOG_FILE ".%d"), i) == -1) {
@@ -728,13 +801,12 @@ static void choose_recovery_file(Device* device) {
}
if ((ensure_path_mounted(filename) != 0) || (access(filename, R_OK) == -1)) {
free(filename);
- entries[i+1] = NULL;
+ entries[n++] = NULL;
break;
}
- entries[i+1] = filename;
+ entries[n++] = filename;
}
- entries[0] = strdup("Go back");
title_headers = prepend_title((const char**)headers);
while(1) {
@@ -743,7 +815,7 @@ static void choose_recovery_file(Device* device) {
file_to_ui(entries[chosen_item]);
}
- for (i = 0; i < KEEP_LOG_COUNT + 1; i++) {
+ for (i = 0; i < (sizeof(entries) / sizeof(*entries)); i++) {
free(entries[i]);
}
}
@@ -909,10 +981,6 @@ ui_print(const char* format, ...) {
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);
redirect_stdio(TEMPORARY_LOG_FILE);
@@ -924,41 +992,15 @@ main(int argc, char **argv) {
// 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]);
+ if (argc == 2 && strcmp(argv[1], "--adbd") == 0) {
+ adb_main();
return 0;
}
-<<<<<<< HEAD
- 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);
+ printf("Starting recovery (pid %d) on %s", getpid(), ctime(&start));
load_volume_table();
ensure_path_mounted(LAST_LOG_FILE);
-
rotate_last_logs(KEEP_LOG_COUNT);
get_args(&argc, &argv);
@@ -966,7 +1008,6 @@ main(int argc, char **argv) {
const char *update_package = NULL;
int wipe_data = 0, wipe_cache = 0, show_text = 0;
bool just_exit = false;
- bool perform_backup = false;
bool shutdown_after = false;
int arg;
@@ -1027,7 +1068,7 @@ main(int argc, char **argv) {
ui->Print("Warning: No file_contexts\n");
}
- //device->StartRecovery();
+ device->StartRecovery();
printf("Command:");
for (arg = 0; arg < argc; arg++) {
@@ -1055,52 +1096,15 @@ main(int argc, char **argv) {
property_get("ro.build.display.id", recovery_version, "");
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");
- LOGI("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);
- }
- 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, true);
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");
@@ -1114,66 +1118,18 @@ main(int argc, char **argv) {
}
}
} 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 (erase_persistent_partition() == -1 ) 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 (wipe_cache && erase_volume("/cache")) status = INSTALL_ERROR;
if (status != INSTALL_SUCCESS) ui->Print("Cache wipe failed.\n");
} else if (!just_exit) {
status = INSTALL_NONE; // No command specified
ui->SetBackground(RecoveryUI::NO_COMMAND);
}
- }
-
- 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") && TWFunc::Path_Exists("/system/etc/install-recovery.sh")) {
- 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);
- }
if (status == INSTALL_ERROR || status == INSTALL_CORRUPT) {
copy_logs();
@@ -1187,27 +1143,6 @@ main(int argc, char **argv) {
// Save logs and clean up before rebooting or shutting down.
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
- property_set(ANDROID_RB_PROPERTY, "reboot,");
switch (after) {
case Device::SHUTDOWN: