diff options
Diffstat (limited to '')
-rw-r--r-- | recovery.cpp | 193 |
1 files changed, 98 insertions, 95 deletions
diff --git a/recovery.cpp b/recovery.cpp index 0f0b978e7..c7d840dd6 100644 --- a/recovery.cpp +++ b/recovery.cpp @@ -41,16 +41,19 @@ #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/properties.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 <cutils/properties.h> /* for property_list */ #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 +62,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 +99,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 +133,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 +192,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,19 +207,20 @@ 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); } bool is_ro_debuggable() { - char value[PROPERTY_VALUE_MAX+1]; - return (property_get("ro.debuggable", value, NULL) == 1 && value[0] == '1'); + return android::base::GetBoolProperty("ro.debuggable", false); } 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: @@ -1271,15 +1264,12 @@ prompt_and_wait(Device* device, int status) { break; case Device::MOUNT_SYSTEM: - char system_root_image[PROPERTY_VALUE_MAX]; - property_get("ro.build.system_root_image", system_root_image, ""); - // For a system image built with the root directory (i.e. // system_root_image == "true"), we mount it to /system_root, and symlink /system // to /system_root/system to make adb shell work (the symlink is created through // the build system). // Bug: 22855115 - if (strcmp(system_root_image, "true") == 0) { + if (android::base::GetBoolProperty("ro.build.system_root_image", false)) { if (ensure_path_mounted_at("/", "/system_root") != -1) { ui->Print("Mounted /system.\n"); } @@ -1336,6 +1326,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 +1414,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,11 +1438,11 @@ static void log_failure_code(ErrorCode code, const char *update_package) { }; std::string log_content = android::base::Join(log_buffer, "\n"); if (!android::base::WriteStringToFile(log_content, TEMPORARY_INSTALL_FILE)) { - LOGE("failed to write %s: %s\n", TEMPORARY_INSTALL_FILE, strerror(errno)); + PLOG(ERROR) << "failed to write " << TEMPORARY_INSTALL_FILE; } // Also write the info into last_log. - LOGI("%s\n", log_content.c_str()); + LOG(INFO) << log_content; } static ssize_t logbasename( @@ -1469,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()) && @@ -1485,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); } } @@ -1494,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? @@ -1514,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; } @@ -1531,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; @@ -1549,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; @@ -1581,7 +1585,7 @@ int main(int argc, char **argv) { break; } case '?': - LOGE("Invalid command argument\n"); + LOG(ERROR) << "Invalid command argument"; continue; } } @@ -1690,8 +1694,7 @@ int main(int argc, char **argv) { ui->Print("Retry attempt %d\n", retry_count); // Reboot and retry the update - int ret = property_set(ANDROID_RB_PROPERTY, "reboot,recovery"); - if (ret < 0) { + if (!android::base::SetProperty(ANDROID_RB_PROPERTY, "reboot,recovery")) { ui->Print("Reboot failed\n"); } else { while (true) { @@ -1766,22 +1769,22 @@ 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: ui->Print("Shutting down...\n"); - property_set(ANDROID_RB_PROPERTY, "shutdown,"); + android::base::SetProperty(ANDROID_RB_PROPERTY, "shutdown,"); break; case Device::REBOOT_BOOTLOADER: ui->Print("Rebooting to bootloader...\n"); - property_set(ANDROID_RB_PROPERTY, "reboot,bootloader"); + android::base::SetProperty(ANDROID_RB_PROPERTY, "reboot,bootloader"); break; default: ui->Print("Rebooting...\n"); - property_set(ANDROID_RB_PROPERTY, "reboot,"); + android::base::SetProperty(ANDROID_RB_PROPERTY, "reboot,"); break; } while (true) { |