summaryrefslogtreecommitdiffstats
path: root/recovery.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'recovery.cpp')
-rw-r--r--recovery.cpp171
1 files changed, 89 insertions, 82 deletions
diff --git a/recovery.cpp b/recovery.cpp
index ccb2d223b..d3f9c47ae 100644
--- a/recovery.cpp
+++ b/recovery.cpp
@@ -41,16 +41,18 @@
#include <adb.h>
#include <android/log.h> /* Android Log Priority Tags */
#include <android-base/file.h>
+#include <android-base/logging.h>
#include <android-base/parseint.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
+#include <android-base/unique_fd.h>
#include <bootloader_message/bootloader_message.h>
#include <cutils/android_reboot.h>
#include <cutils/properties.h>
-#include <log/logger.h> /* Android Log packet format */
-#include <private/android_logger.h> /* private pmsg functions */
-
#include <healthd/BatteryMonitor.h>
+#include <private/android_logger.h> /* private pmsg functions */
+#include <selinux/label.h>
+#include <selinux/selinux.h>
#include "adb_install.h"
#include "common.h"
@@ -59,18 +61,17 @@
#include "fuse_sdcard_provider.h"
#include "fuse_sideload.h"
#include "install.h"
+#include "minadbd/minadbd.h"
#include "minui/minui.h"
#include "minzip/DirUtil.h"
#include "minzip/Zip.h"
#include "roots.h"
#include "ui.h"
-#include "unique_fd.h"
#include "screen_ui.h"
struct selabel_handle *sehandle;
static const struct option OPTIONS[] = {
- { "send_intent", required_argument, NULL, 'i' },
{ "update_package", required_argument, NULL, 'u' },
{ "retry_count", required_argument, NULL, 'n' },
{ "wipe_data", no_argument, NULL, 'w' },
@@ -97,7 +98,6 @@ static const std::vector<std::string> bootreason_blacklist {
static const char *CACHE_LOG_DIR = "/cache/recovery";
static const char *COMMAND_FILE = "/cache/recovery/command";
-static const char *INTENT_FILE = "/cache/recovery/intent";
static const char *LOG_FILE = "/cache/recovery/log";
static const char *LAST_INSTALL_FILE = "/cache/recovery/last_install";
static const char *LOCALE_FILE = "/cache/recovery/last_locale";
@@ -132,10 +132,8 @@ static bool has_cache = false;
* The recovery tool communicates with the main system through /cache files.
* /cache/recovery/command - INPUT - command line for tool, one arg per line
* /cache/recovery/log - OUTPUT - combined log file from recovery run(s)
- * /cache/recovery/intent - OUTPUT - intent that was passed in
*
* The arguments which may be supplied in the recovery.command file:
- * --send_intent=anystring - write the text out to recovery.intent
* --update_package=path - verify install an OTA package file
* --wipe_data - erase user data (and cache), then reboot
* --wipe_cache - wipe cache (but not user data), then reboot
@@ -193,7 +191,7 @@ static const int MAX_ARGS = 100;
// open a given path, mounting partitions as necessary
FILE* fopen_path(const char *path, const char *mode) {
if (ensure_path_mounted(path) != 0) {
- LOGE("Can't mount %s\n", path);
+ LOG(ERROR) << "Can't mount " << path;
return NULL;
}
@@ -208,7 +206,9 @@ FILE* fopen_path(const char *path, const char *mode) {
// close a file, log an error if the error indicator is set
static void check_and_fclose(FILE *fp, const char *name) {
fflush(fp);
- if (ferror(fp)) LOGE("Error in %s\n(%s)\n", name, strerror(errno));
+ if (ferror(fp)) {
+ PLOG(ERROR) << "Error in " << name;
+ }
fclose(fp);
}
@@ -220,7 +220,7 @@ bool is_ro_debuggable() {
static void redirect_stdio(const char* filename) {
int pipefd[2];
if (pipe(pipefd) == -1) {
- LOGE("pipe failed: %s\n", strerror(errno));
+ PLOG(ERROR) << "pipe failed";
// Fall back to traditional logging mode without timestamps.
// If these fail, there's not really anywhere to complain...
@@ -232,7 +232,7 @@ static void redirect_stdio(const char* filename) {
pid_t pid = fork();
if (pid == -1) {
- LOGE("fork failed: %s\n", strerror(errno));
+ PLOG(ERROR) << "fork failed";
// Fall back to traditional logging mode without timestamps.
// If these fail, there's not really anywhere to complain...
@@ -251,14 +251,14 @@ static void redirect_stdio(const char* filename) {
// Child logger to actually write to the log file.
FILE* log_fp = fopen(filename, "a");
if (log_fp == nullptr) {
- LOGE("fopen \"%s\" failed: %s\n", filename, strerror(errno));
+ PLOG(ERROR) << "fopen \"" << filename << "\" failed";
close(pipefd[0]);
_exit(1);
}
FILE* pipe_fp = fdopen(pipefd[0], "r");
if (pipe_fp == nullptr) {
- LOGE("fdopen failed: %s\n", strerror(errno));
+ PLOG(ERROR) << "fdopen failed";
check_and_fclose(log_fp, filename);
close(pipefd[0]);
_exit(1);
@@ -278,7 +278,7 @@ static void redirect_stdio(const char* filename) {
fflush(log_fp);
}
- LOGE("getline failed: %s\n", strerror(errno));
+ PLOG(ERROR) << "getline failed";
free(line);
check_and_fclose(log_fp, filename);
@@ -293,10 +293,10 @@ static void redirect_stdio(const char* filename) {
setbuf(stderr, nullptr);
if (dup2(pipefd[1], STDOUT_FILENO) == -1) {
- LOGE("dup2 stdout failed: %s\n", strerror(errno));
+ PLOG(ERROR) << "dup2 stdout failed";
}
if (dup2(pipefd[1], STDERR_FILENO) == -1) {
- LOGE("dup2 stderr failed: %s\n", strerror(errno));
+ PLOG(ERROR) << "dup2 stderr failed";
}
close(pipefd[1]);
@@ -312,18 +312,20 @@ get_args(int *argc, char ***argv) {
bootloader_message boot = {};
std::string err;
if (!read_bootloader_message(&boot, &err)) {
- LOGE("%s\n", err.c_str());
+ LOG(ERROR) << err;
// If fails, leave a zeroed bootloader_message.
memset(&boot, 0, sizeof(boot));
}
stage = strndup(boot.stage, sizeof(boot.stage));
if (boot.command[0] != 0 && boot.command[0] != 255) {
- LOGI("Boot command: %.*s\n", (int)sizeof(boot.command), boot.command);
+ std::string boot_command = std::string(boot.command, sizeof(boot.command));
+ LOG(INFO) << "Boot command: " << boot_command;
}
if (boot.status[0] != 0 && boot.status[0] != 255) {
- LOGI("Boot status: %.*s\n", (int)sizeof(boot.status), boot.status);
+ std::string boot_status = std::string(boot.status, sizeof(boot.status));
+ LOG(INFO) << "Boot status: " << boot_status;
}
// --- if arguments weren't supplied, look in the bootloader control block
@@ -337,9 +339,10 @@ get_args(int *argc, char ***argv) {
if ((arg = strtok(NULL, "\n")) == NULL) break;
(*argv)[*argc] = strdup(arg);
}
- LOGI("Got arguments from boot message\n");
+ LOG(INFO) << "Got arguments from boot message";
} else if (boot.recovery[0] != 0 && boot.recovery[0] != 255) {
- LOGE("Bad boot message\n\"%.20s\"\n", boot.recovery);
+ std::string boot_recovery = std::string(boot.recovery, 20);
+ LOG(ERROR) << "Bad boot message\n" << "\"" <<boot_recovery << "\"";
}
}
@@ -364,7 +367,7 @@ get_args(int *argc, char ***argv) {
}
check_and_fclose(fp, COMMAND_FILE);
- LOGI("Got arguments from %s\n", COMMAND_FILE);
+ LOG(INFO) << "Got arguments from " << COMMAND_FILE;
}
}
@@ -378,7 +381,7 @@ get_args(int *argc, char ***argv) {
strlcat(boot.recovery, "\n", sizeof(boot.recovery));
}
if (!write_bootloader_message(boot, &err)) {
- LOGE("%s\n", err.c_str());
+ LOG(ERROR) << err;
}
}
@@ -389,7 +392,7 @@ set_sdcard_update_bootloader_message() {
strlcpy(boot.recovery, "recovery\n", sizeof(boot.recovery));
std::string err;
if (!write_bootloader_message(boot, &err)) {
- LOGE("%s\n", err.c_str());
+ LOG(ERROR) << err;
}
}
@@ -397,14 +400,14 @@ set_sdcard_update_bootloader_message() {
static void save_kernel_log(const char* destination) {
int klog_buf_len = klogctl(KLOG_SIZE_BUFFER, 0, 0);
if (klog_buf_len <= 0) {
- LOGE("Error getting klog size: %s\n", strerror(errno));
+ PLOG(ERROR) << "Error getting klog size";
return;
}
std::string buffer(klog_buf_len, 0);
int n = klogctl(KLOG_READ_ALL, &buffer[0], klog_buf_len);
if (n == -1) {
- LOGE("Error in reading klog: %s\n", strerror(errno));
+ PLOG(ERROR) << "Error in reading klog";
return;
}
buffer.resize(n);
@@ -424,17 +427,17 @@ static void copy_log_file_to_pmsg(const char* source, const char* destination) {
}
// How much of the temp log we have copied to the copy in cache.
-static long tmplog_offset = 0;
+static off_t tmplog_offset = 0;
static void copy_log_file(const char* source, const char* destination, bool append) {
FILE* dest_fp = fopen_path(destination, append ? "a" : "w");
if (dest_fp == nullptr) {
- LOGE("Can't open %s\n", destination);
+ PLOG(ERROR) << "Can't open " << destination;
} else {
FILE* source_fp = fopen(source, "r");
if (source_fp != nullptr) {
if (append) {
- fseek(source_fp, tmplog_offset, SEEK_SET); // Since last write
+ fseeko(source_fp, tmplog_offset, SEEK_SET); // Since last write
}
char buf[4096];
size_t bytes;
@@ -442,7 +445,7 @@ static void copy_log_file(const char* source, const char* destination, bool appe
fwrite(buf, 1, bytes, dest_fp);
}
if (append) {
- tmplog_offset = ftell(source_fp);
+ tmplog_offset = ftello(source_fp);
}
check_and_fclose(source_fp, source);
}
@@ -516,22 +519,10 @@ static void copy_logs() {
}
// clear the recovery command and prepare to boot a (hopefully working) system,
-// copy our log file to cache as well (for the system to read), and
-// record any intent we were asked to communicate back to the system.
-// this function is idempotent: call it as many times as you like.
+// copy our log file to cache as well (for the system to read). This function is
+// idempotent: call it as many times as you like.
static void
-finish_recovery(const char *send_intent) {
- // By this point, we're ready to return to the main system...
- if (send_intent != NULL && has_cache) {
- FILE *fp = fopen_path(INTENT_FILE, "w");
- if (fp == NULL) {
- LOGE("Can't open %s\n", INTENT_FILE);
- } else {
- fputs(send_intent, fp);
- check_and_fclose(fp, INTENT_FILE);
- }
- }
-
+finish_recovery() {
// Save the locale to cache, so if recovery is next started up
// without a --locale argument (eg, directly from the bootloader)
// it will use the last-known locale.
@@ -539,12 +530,14 @@ finish_recovery(const char *send_intent) {
size_t len = strlen(locale);
__pmsg_write(LOCALE_FILE, locale, len);
if (has_cache) {
- LOGI("Saving locale \"%s\"\n", locale);
+ LOG(INFO) << "Saving locale \"" << locale << "\"";
FILE* fp = fopen_path(LOCALE_FILE, "w");
- fwrite(locale, 1, len, fp);
- fflush(fp);
- fsync(fileno(fp));
- check_and_fclose(fp, LOCALE_FILE);
+ if (fp != NULL) {
+ fwrite(locale, 1, len, fp);
+ fflush(fp);
+ fsync(fileno(fp));
+ check_and_fclose(fp, LOCALE_FILE);
+ }
}
}
@@ -554,13 +547,13 @@ finish_recovery(const char *send_intent) {
bootloader_message boot = {};
std::string err;
if (!write_bootloader_message(boot, &err)) {
- LOGE("%s\n", err.c_str());
+ LOG(ERROR) << err;
}
// Remove the command file, so recovery won't repeat indefinitely.
if (has_cache) {
if (ensure_path_mounted(COMMAND_FILE) != 0 || (unlink(COMMAND_FILE) && errno != ENOENT)) {
- LOGW("Can't unlink %s\n", COMMAND_FILE);
+ LOG(WARNING) << "Can't unlink " << COMMAND_FILE;
}
ensure_path_unmounted(CACHE_ROOT);
}
@@ -700,7 +693,7 @@ get_menu_selection(const char* const * headers, const char* const * items,
if (ui->WasTextEverVisible()) {
continue;
} else {
- LOGI("timed out waiting for key input; rebooting.\n");
+ LOG(INFO) << "timed out waiting for key input; rebooting.";
ui->EndMenu();
return 0; // XXX fixme
}
@@ -741,7 +734,7 @@ static char* browse_directory(const char* path, Device* device) {
DIR* d = opendir(path);
if (d == NULL) {
- LOGE("error opening %s: %s\n", path, strerror(errno));
+ PLOG(ERROR) << "error opening " << path;
return NULL;
}
@@ -884,35 +877,35 @@ static bool wipe_cache(bool should_confirm, Device* device) {
// Otherwise, it goes with BLKDISCARD (if device supports BLKDISCARDZEROES) or
// BLKZEROOUT.
static bool secure_wipe_partition(const std::string& partition) {
- unique_fd fd(TEMP_FAILURE_RETRY(open(partition.c_str(), O_WRONLY)));
- if (fd.get() == -1) {
- LOGE("failed to open \"%s\": %s\n", partition.c_str(), strerror(errno));
+ android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(partition.c_str(), O_WRONLY)));
+ if (fd == -1) {
+ PLOG(ERROR) << "failed to open \"" << partition << "\"";
return false;
}
uint64_t range[2] = {0, 0};
- if (ioctl(fd.get(), BLKGETSIZE64, &range[1]) == -1 || range[1] == 0) {
- LOGE("failed to get partition size: %s\n", strerror(errno));
+ if (ioctl(fd, BLKGETSIZE64, &range[1]) == -1 || range[1] == 0) {
+ PLOG(ERROR) << "failed to get partition size";
return false;
}
printf("Secure-wiping \"%s\" from %" PRIu64 " to %" PRIu64 ".\n",
partition.c_str(), range[0], range[1]);
printf("Trying BLKSECDISCARD...\t");
- if (ioctl(fd.get(), BLKSECDISCARD, &range) == -1) {
+ if (ioctl(fd, BLKSECDISCARD, &range) == -1) {
printf("failed: %s\n", strerror(errno));
// Use BLKDISCARD if it zeroes out blocks, otherwise use BLKZEROOUT.
unsigned int zeroes;
- if (ioctl(fd.get(), BLKDISCARDZEROES, &zeroes) == 0 && zeroes != 0) {
+ if (ioctl(fd, BLKDISCARDZEROES, &zeroes) == 0 && zeroes != 0) {
printf("Trying BLKDISCARD...\t");
- if (ioctl(fd.get(), BLKDISCARD, &range) == -1) {
+ if (ioctl(fd, BLKDISCARD, &range) == -1) {
printf("failed: %s\n", strerror(errno));
return false;
}
} else {
printf("Trying BLKZEROOUT...\t");
- if (ioctl(fd.get(), BLKZEROOUT, &range) == -1) {
+ if (ioctl(fd, BLKZEROOUT, &range) == -1) {
printf("failed: %s\n", strerror(errno));
return false;
}
@@ -928,18 +921,18 @@ static bool secure_wipe_partition(const std::string& partition) {
// 2. check metadata (ota-type, pre-device and serial number if having one).
static bool check_wipe_package(size_t wipe_package_size) {
if (wipe_package_size == 0) {
- LOGE("wipe_package_size is zero.\n");
+ LOG(ERROR) << "wipe_package_size is zero";
return false;
}
std::string wipe_package;
std::string err_str;
if (!read_wipe_package(&wipe_package, wipe_package_size, &err_str)) {
- LOGE("Failed to read wipe package: %s\n", err_str.c_str());
+ PLOG(ERROR) << "Failed to read wipe package";
return false;
}
if (!verify_package(reinterpret_cast<const unsigned char*>(wipe_package.data()),
wipe_package.size())) {
- LOGE("Failed to verify package.\n");
+ LOG(ERROR) << "Failed to verify package";
return false;
}
@@ -948,7 +941,7 @@ static bool check_wipe_package(size_t wipe_package_size) {
int err = mzOpenZipArchive(reinterpret_cast<unsigned char*>(&wipe_package[0]),
wipe_package.size(), &zip);
if (err != 0) {
- LOGE("Can't open wipe package: %s\n", err != -1 ? strerror(err) : "bad");
+ LOG(ERROR) << "Can't open wipe package";
return false;
}
std::string metadata;
@@ -990,12 +983,12 @@ static bool wipe_ab_device(size_t wipe_package_size) {
ui->SetProgressType(RecoveryUI::INDETERMINATE);
if (!check_wipe_package(wipe_package_size)) {
- LOGE("Failed to verify wipe package\n");
+ LOG(ERROR) << "Failed to verify wipe package";
return false;
}
std::string partition_list;
if (!android::base::ReadFileToString(RECOVERY_WIPE, &partition_list)) {
- LOGE("failed to read \"%s\".\n", RECOVERY_WIPE);
+ LOG(ERROR) << "failed to read \"" << RECOVERY_WIPE << "\"";
return false;
}
@@ -1158,7 +1151,7 @@ static int apply_from_sdcard(Device* device, bool* wipe_cache) {
sleep(1);
continue;
} else {
- LOGE("Timed out waiting for the fuse-provided package.\n");
+ LOG(ERROR) << "Timed out waiting for the fuse-provided package.";
result = INSTALL_ERROR;
kill(child, SIGKILL);
break;
@@ -1180,7 +1173,7 @@ static int apply_from_sdcard(Device* device, bool* wipe_cache) {
}
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
- LOGE("Error exit from the fuse process: %d\n", WEXITSTATUS(status));
+ LOG(ERROR) << "Error exit from the fuse process: " << WEXITSTATUS(status);
}
ensure_path_unmounted(SDCARD_ROOT);
@@ -1193,7 +1186,7 @@ static int apply_from_sdcard(Device* device, bool* wipe_cache) {
static Device::BuiltinAction
prompt_and_wait(Device* device, int status) {
for (;;) {
- finish_recovery(NULL);
+ finish_recovery();
switch (status) {
case INSTALL_SUCCESS:
case INSTALL_NONE:
@@ -1336,6 +1329,18 @@ ui_print(const char* format, ...) {
}
}
+static constexpr char log_characters[] = "VDIWEF";
+
+void UiLogger(android::base::LogId id, android::base::LogSeverity severity,
+ const char* tag, const char* file, unsigned int line,
+ const char* message) {
+ if (severity >= android::base::ERROR && gCurrentUI != NULL) {
+ gCurrentUI->Print("E:%s\n", message);
+ } else {
+ fprintf(stdout, "%c:%s\n", log_characters[severity], message);
+ }
+}
+
static bool is_battery_ok() {
struct healthd_config healthd_config = {
.batteryStatusPath = android::String8(android::String8::kEmptyString),
@@ -1412,7 +1417,7 @@ static void set_retry_bootloader_message(int retry_count, int argc, char** argv)
}
std::string err;
if (!write_bootloader_message(boot, &err)) {
- LOGE("%s\n", err.c_str());
+ LOG(ERROR) << err;
}
}
@@ -1436,7 +1441,7 @@ static void log_failure_code(ErrorCode code, const char *update_package) {
fprintf(install_log, "error: %d\n", code);
fclose(install_log);
} else {
- LOGE("failed to open last_install: %s\n", strerror(errno));
+ PLOG(ERROR) << "failed to open last_install";
}
}
@@ -1466,7 +1471,7 @@ static ssize_t logrotate(
}
std::string name(filename);
- size_t dot = name.find_last_of(".");
+ size_t dot = name.find_last_of('.');
std::string sub = name.substr(0, dot);
if (!strstr(LAST_KMSG_FILE, sub.c_str()) &&
@@ -1482,7 +1487,7 @@ static ssize_t logrotate(
if (!isdigit(number.data()[0])) {
name += ".1";
} else {
- unsigned long long i = std::stoull(number);
+ auto i = std::stoull(number);
name = sub + "." + std::to_string(i + 1);
}
}
@@ -1491,6 +1496,10 @@ static ssize_t logrotate(
}
int main(int argc, char **argv) {
+ // We don't have logcat yet under recovery; so we'll print error on screen and
+ // log to stdout (which is redirected to recovery.log) as we used to do.
+ android::base::InitLogging(argv, &UiLogger);
+
// Take last pmsg contents and rewrite it to the current pmsg session.
static const char filter[] = "recovery/";
// Do we need to rotate?
@@ -1511,7 +1520,7 @@ int main(int argc, char **argv) {
// 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 == 2 && strcmp(argv[1], "--adbd") == 0) {
- adb_server_main(0, DEFAULT_ADB_PORT, -1);
+ minadbd_main();
return 0;
}
@@ -1528,7 +1537,6 @@ int main(int argc, char **argv) {
get_args(&argc, &argv);
- const char *send_intent = NULL;
const char *update_package = NULL;
bool should_wipe_data = false;
bool should_wipe_cache = false;
@@ -1546,7 +1554,6 @@ int main(int argc, char **argv) {
int option_index;
while ((arg = getopt_long(argc, argv, "", OPTIONS, &option_index)) != -1) {
switch (arg) {
- case 'i': send_intent = optarg; break;
case 'n': android::base::ParseInt(optarg, &retry_count, 0); break;
case 'u': update_package = optarg; break;
case 'w': should_wipe_data = true; break;
@@ -1578,7 +1585,7 @@ int main(int argc, char **argv) {
break;
}
case '?':
- LOGE("Invalid command argument\n");
+ LOG(ERROR) << "Invalid command argument";
continue;
}
}
@@ -1763,7 +1770,7 @@ int main(int argc, char **argv) {
}
// Save logs and clean up before rebooting or shutting down.
- finish_recovery(send_intent);
+ finish_recovery();
switch (after) {
case Device::SHUTDOWN: